Why You Should Never Use jQuery Live

by Justin Meyer

Why You Should Never Use jQuery Live

Justin Meyer Event delegation is a powerful technique that is often used in JavaScript applications. jQuery has two similar API methods that provide similar event delegation functionality - live and delegate.

posted in Development on April 6, 2011 by Justin Meyer

Event delegation is a powerful technique that is often used in
JavaScript applications. jQuery has two similar API methods that provide
similar event delegation functionality: live and delegate.

On the surface live and delegate can seem interchangeable. However, they
are not. Live has several serious disadvantages and should never be
used
, and this article will explain why.

Event Delegation 101

First, a quick review. Event delegation works by binding to an element
in the page, waiting for a DOM event to bubble to this element, and in
the event handler, checking if a parent of the target element matches a
selector you are looking for. If a match is found, your handler is
called.

For example, if you want to ‘manually’ delegate on clicks for “tr”
elements inside a table with the ID attribute “mytable”, you might do
something like:

$("#mytable").bind('click', function(ev){
  var current = ev.target
  while( !/tr/i.test(current.nodeName) && 
         current !== this ){
    current = current.parentNode
  }
  if( current !== this ){
    // do stuff !!
  }
})

How Live and Delegate Work

Here’s similar code but done with jQuery’s delegate and live:

$('#mytable').delegate('tr', 'click', function(event) {…});
$('#mytable tr').live('click', function(event) {…});

The critical difference is .live binds to the document element while
delegate binds to whatever element its called on, in this case the
#mytable element.

In the delegate example above, when a user clicks inside a tr element,
this event bubbles up to the table, which triggers the delegate click
handler. There it checks if the any of the event’s target’s parents (or
the target itself) matches the selector, “tr”. If it does, it runs the
delegate event handler.

In the live example, jQuery binds a click handler to the top-most
element in the DOM, the document element. Any click in the page will
bubble up the DOM to this element and trigger this click handler. It
will check if the elements above the thing we clicked, or the event
target itself, match “#mytable tr”. Assuming the user clicked a tr or
something inside a tr within #mytable, its parent chain will contain a
match, so the live callback will run.

Now that its clear how they work, we can discuss how live could cause
problems in your application.

1. You can’t use live for reusable widgets.

Let’s say we are creating a tab widget. We want to delegate on all
div.tab clicks inside our widget. Since live binds to the document
element, if we put 2 tab widgets in the page, both of their click
handlers will ALWAYS be invoked. This is not what we want! With
delegate, we can listen ONLY on the tab widget’s parent element, so
clicking the first tab widget will not invoke the click handler of the
second widget.

<html>
  <div class=”tab1 tabwidget”>
    <div class=”tab”>…</tab>
    <div class=”tab>…</tab>
  </div>
<div class=”tab2 tabwidget”>
    <div class=”tab”>…</tab>
    <div class=”tab>…</tab>
  </div>
</html>

Live binds to the HTML element, so in a sense all live handlers are
“global”. Delegate only listens to .tab1 or .tab2, so it is localized to
only the widget we’re working on.

2. stopPropagate() doesn’t work in live

As illustrated above, live actually binds an event handler to the top
element in the page, so calling stopPropagate won’t do anything. The
event has already traveled as far as it can propagate.

By contrast, calling stopPropagate in a delegate handler will prevent
the event from bubbling above the tab’s parent element.

3. Live is slower

Returning to the code sample above, the live example will do a query for
all “#mytable tr a” elements in the page, then ignore that result and
bind to the document element. This first query is completely useless and
wasteful.

Also, live traverses all DOM nodes between the event target and the
document element to check for a match with the given selector. Delegate
only traverses DOM nodes between the event target and the given parent
element to check for a match. Traversing parent elements in the DOM is
the slowest part of event delegation, so live handlers will be slower to
respond to events.

4. Live isn’t chainable

Everyone is used to chaining jQuery methods together and not thinking
twice about it. Live breaks chaining functionality, which might
introduce tricky bugs. Since that first query is used as the selector
for the live handler, the context gets changed, so chaining a method
after a .live() call won’t do what you expect.

Rolling your own

You might be thinking, who needs delegate when I can do this myself? You
can certainly write your own event delegation, like this:

$(“#mytable”).bind(“click”, function(ev){
  var $a = $(event.target).closest(“tr a”);
  if($a.length) // we have a match, run the click code
});

The disadvantage to this becomes apparent when you delegate for multiple
selectors on the same parent element. For example, say you want to bind
to all “tr a .edit” selectors in your table also. If you’re using
delegate, it will batch the .closest call (which is the slowest part of
event delegation). If you roll your own handlers, you’ll end up with
multiple calls to .closest, which means walking up the parent tree more
times than is needed, so your event delegation performance will suffer.

Conclusion

As a general best practice, never use .live in your applications. After
live was introduced in jQuery, Justin
argued
the need for better a event delegation API, and delegate was created.
The main reason jQuery still supports live is for legacy code.

blog comments powered by Disqus

CanJS 2.2 Release

Justin Meyerposted in Development, Open Source, Uncategorized on April 5, 2015 by Justin MeyerCanJS 2.2 is out. It's awesome. This article covers the top 10 enhancements added since 2.1. Some of the improvements include Browserify and StealJS support, can-EVENT arguments, observable promises, and in-page automatically rendered templates. The article includes a lot of good JSBins to learn from too.

Getting Started with Cordova

Brian Moschelposted in Development on March 26, 2015 by Brian MoschelAt Bitovi, we’re big fans of building applications with web technologies and using build tools to target other platforms like iOS, Android, and desktop. This article will provide a quick guide to getting up and running quickly with Cordova.

Contact Us
(312) 620-0386 | contact@bitovi.com
 or cancel