views:

58

answers:

1

Reading another SO question about jQuery performance, I started thinking about the point when it becomes worth using event delegation rather than binding to elements individually. I was thinking mainly about jQuery, but I suppose it is probably applicable for Javascript in general.

Event delegation has two main purposes:

  1. allowing handlers to work on elements that have not yet been created/inserted into the DOM.
  2. binding one function to a common ancestor element rather than to multiple sibling elements

My question is about the second of these. The general answer will probably be "it depends on the exact situation", but I wonder if there is a rule of thumb or a way of benchmarking in order to test this.

So, the question is: how many elements do you need before the performance benefits of event delegation outweigh the performance costs?

+3  A: 

Assuming this HTML structure:

<ul id="navUL">
    <li><a href="one.html">One</a></li>
    <li><a href="two.html">Two</a></li>
    <li><a href="three.html">Three</a></li>
</ul>

Just to clear things up (for me) .... According to jQuery docs ( http://api.jquery.com/delegate/ ), this:

$("#navUL").delegate("a", "click", function(){
    // anchor clicked
});  

... is equivalent to this:

$("#navUL").each(function(){
    $("a", this).live("click", function(){
        // anchor clicked
    });
}); 

However, event delegation (as I know it) is this:

$("#navUL").click(function(e) {
    if (e.target.nodeName !== "A") { return false; }
    // anchor clicked
    // anchor is referenced by e.target
});  

So you catch the click event on the UL element, and then figure out which anchor was actually clicked via the event.target property.

I don't know about the delegate() method, but this last technique should always be faster than attaching event handlers to each anchor in the #navUL element, like so:

$("#navUL a").click(function() {
    // anchor clicked
    // anchor is referenced by the this value
});
Šime Vidas
Don't you need an `e.stopPropagation();` in your delegation as you know it example?
Peter Ajtai
Hm, why? The user clicks somewhere inside the #navUL element. The click event propagates to the #navUL element (since there are no click handlers attached to A or LI elements). Inside the #navUL click handler, I check if an anchor was clicked. If not, I just kill the event (via return false;). If yes, I do what I intended (with the anchor). I may want to prevent the default behavior of the anchor, but I don't see why I would want to prevent the click event from bubbling up the DOM tree (I don't have any click handlers set on ancestor elements, anyway).
Šime Vidas
Yeah, you're right.
Peter Ajtai
@Sime OK, I can go with the "always" answer. It fits with what I do anyway. Thanks.
lonesomeday