Kevin
Kevin

Reputation: 23634

Why is event delegation better in this case of DOM manipulation

<div id="tours">
  <h1>Guided Tours</h1>
  <ul>
    <li class="usa tour" data-discount="299">
      <h2>New York, New York</h2>
      <span class="details">$1,899 for 7 nights</span>
      <button class="book">Book Now</button>
    </li>
    <li class="europe tour" data-discount="176">
      <h2>Paris, France</h2>
      <span class="details">$2,299 for 7 nights</span>
      <button class="book">Book Now</button>
    </li>
    <li class="asia tour" data-discount="349">
      <h2>Tokyo, Japan</h2>
      <span class="details">$3,799 for 7 nights</span>
      <button class="book">Book Now</button>
    </li>
  </ul>
</div>

The above is HTML code and below is the DOM manipulation part.

$(document).ready(function(){
  $("li.tour button.book").on("click", function(){
    var tour = $(this).closest(".tour");
    var discount = tour.data("discount");
    var message = $("<span>Call 1-555-jquery-air for a $" + discount + "</span>");
    tour.append(message);
    $(this).remove();
  });
});

The above code works fine. But it seems the right way to do the approach is below and they call it as event delegation

$(document).ready(function(){
  $("li.tour").on("click", "button", function(){
    var tour = $(this).closest(".tour");
    var discount = tour.data("discount");
    var message = $("<span>Call 1-555-jquery-air for a $" + discount + "</span>");
    tour.append(message);
    $(this).remove();
  });
});

Upvotes: 0

Views: 148

Answers (2)

dezman
dezman

Reputation: 19358

Your second solution will have better performance if you have a ton of <button>s because jQuery will look for bubbled events on $("li.tour"), instead of attaching event handlers to every <button>, as the docs say: "another advantage of delegated events is their potential for much lower overhead when many elements must be monitored. On a data table with 1,000 rows in its tbody, this example attaches a handler to 1,000 elements"

"Note that for a small amount of elements, and especially with complicated selectors, the filtering that takes place in a delegated event handler can in many cases be slower than just attaching four seperate event handlers" - adeneo

This fiddle here helps explain the difference.

TL;DR

If you have a ton of elements to select, use a delegated event handler.

If you have a complicated selector and not a lot of elements to select, use a regular event handler.

Otherwise, its not a big deal which one you use.

Upvotes: 2

Matt
Matt

Reputation: 75317

As others have pointed out, neither solution is too-distinguishable from the other as it stands, as both will attach an event handler to 3 elements (whether it be a li.tour or a button.book).

To really take advantage of event bubbling, what you'll want to do is;

$(document).ready(function(){
  $("ul").on("click", "button.book", function(){
    var tour = $(this).closest(".tour");
    var discount = tour.data("discount");
    var message = $("<span>Call 1-555-jquery-air for a $" + discount + "</span>");
    tour.append(message);
    $(this).remove();
  });
});

... this way, only 1 event handler is bound to the ul. Event bubbling will mean click's on the button are eventually fired on the ul, which is how jQuery knows a click event has happened.

The advantage here is that you:

  • Aren't looping over 3 elements (only 1).
  • Your DOM has only 1 event handler bound, rather than 3

... obviously this will be a negligible (almost non-existent) benefit for now, but will grow as the amount of elements involved increases.

A small disadvantage is that any click on a descendant of a ul will also bubble to the ul, leaving jQuery to decide (hence a small performance hit) whether to invoke the click handler or not.

Upvotes: 2

Related Questions