tags:

views:

126

answers:

3

why do programmers say that "live" is inefficient?

  1. So what are the alternative methods to replicating that function that are more efficient?
  2. How do we measure the impact of how much it slows things down?
+6  A: 

I suppose it is inefficient because the handler is placed at the root node, and relies on bubbling to catch the event and run the proper handler.

One alternative would be to simply bind your handler to your dynamically created elements when they are created and added to the DOM.

Another alternative is to bind a single handler to a container, and let your events bubble up to that. This can be nice if you have lots of identical elements added to a container.

<div id="myContainer">
    <div class="myElement>element</div>
    <div class="myElement>element</div>
    <div class="myElement>element</div>
    <div class="myElement>element</div>
</div>

Bind a click handler to #myContainer instead of each .myElement.

$('#myContainer').click(function(e) {
    $target = $(e.target);
    if($target.closest('.myElement').length) {
        // Run my code for the click
    }
});

I image this may suffer from some of the same inefficiencies as .live(), but ought to be better as it is more localized. New .myElement items added, automatically work.


EDIT:

According to the docs: As of jQuery 1.4, event bubbling can optionally stop at a DOM element "context".

This would seem to create a similar effect to the last method I mentioned.


EDIT:

As suggested by Nick Craver, jQuery's .delegate() method can produce a similar effect more cleanly.

Example courtesy of Nick:

$('#myContainer').delegate('.myElement', 'click' function() { alert($(this).text()); });
patrick dw
I'd mention `.delegate()` here, a much cleaner way to do your second example :)
Nick Craver
@Nick Craver - doesn't `.delegate()` bind a handler to each element? One nice thing about the method I mentioned is that you don't have the overhead of handlers on multiple elements.
patrick dw
+1 if you give an example :) your current markup would use this: `$('#myContainer').delegate('.myElement', 'click' function() { alert($(this).text()); });`
Nick Craver
@patrick - It binds a handler just like `.live()` using a context (actually `.delegate()` calls `.live()` internally) instead of listening on `document` for bubbles, it listens on the element you bound it to, so it's the same behavior, just grabs the bubble much earlier.
Nick Craver
@Nick Craver - Thanks much. Just took a look at the docs too, and I misunderstood `.delegate()`. Thanks for the tip. I included your solution.
patrick dw
@patrick - +1 for covering th bases :)
Nick Craver
+1  A: 

live() might only be considered inefficient if:

  1. There is a small amount of elements to be bound to an event (< 5, let's say).
  2. The number of these target elements stays fixed.

If your use case meets the criteria above (especially #2) you should stick to binding straight to the elements and avoid live().

An example of benchmarking the performance of live() you can try is by profiling a fragment of code that uses live() to bind a click handler to an element and also profile another fragment of code that uses click() to bind to that same element.

I'm not too sure what end result you'll have but I'm sure it'll be interesting.

bobthabuilda
+1  A: 

As @patrick suggests it can be inefficient because it requires processing for all events on the document, whether the bubble reaches your element or not.

This is where delegate can help as it works in the same way as live but allows it to only effect a smaller proportion of the document by limiting it to a common parent

(using his example)

$('#myContainer').delegate('div.myElement', 'click', function(){});
Simon