Filtering window events by individual events on DOM nodes

Consider the following code example:

import R from 'ramda';
import {Observable} from 'Rx';

var allClicks_ = Observable.fromEvent(window, 'click').share();

var getClicks = function(klass) {
  return allClicks_.filter(e => {
    return R.contains(klass, e.target.classList);
  });
};

getClicks('red').subscribe(x => {
  render('RED: ' + x.target.className);
});

getClicks('blue').subscribe(x => {
  render('BLUE: ' + x.target.className);
});

      

Instead of adding event listeners to ".red" and ".blue" window

events, I added an event listener to ".red" and ".blue" events and filtered events.

Now, what could possibly go wrong with code like this? Is this more (or less) efficient than adding event listeners to individual DOM nodes? Or does it have no performance advantage?

Edit: Share a hot observable so that only one event handler is connected.

+3


source to share


1 answer


This is an example of a delegated event handler. This template is very useful. So useful that libraries like jQuery

and dojo

have built-in support for this pattern (see the selector

jQuery.on and dojo.on argument ).

Adding event handlers to each DOM node is actually an O (n) operation whereas it is an O (1) operation. As the number of matching DOM nodes increases, the delegated event handler pattern gains more advantage.

What could go wrong?



  • If, in this case window

    , an event handler is set between your top-level element ( ) and your target elements, and this event handler is set ev.stopPropagation()

    , then your delegated handler will never see the event.

  • If the filter function is too complex and slow, the browser will have to spend more time than usual using the filter.

  • You will receive events for DOM nodes added after adding event handlers. This is usually seen as a good thing. But if for some reason you didn't expect it, it might leave you.

Note that in your specific example, two handlers are actually registered click

. You can reduce it to one instance with share

:

var allClicks_ = Observable.fromEvent(window, 'click').share();

      

+3


source







All Articles