4

In a bid to write better code and improve how I use jQuery, I've been doing some reading recently. One of the new tips I learnt is using event delegation with jQuery.

While reading, I discovered two "supposed" different methods of addressing it. Below are code snippets to illustrate them.

Assuming I have an HTML block like this:

<html>
  <head>
    <title>Test Code</title>
  </head>
  <body>
    <div id="switcher">
      <button id="button1">Button 1</button>
      <button id="button2">Button 1</button>
      <button id="button3">Button 2</button>
      <button id="button4">Button 3</button>
      <button id="button5">Button 4</button>
      <button id="button5">Button 5</button>
      <button id="button6">Button 6</button>
      <button id="button7">Button 7</button>
      <button id="button8">Button 8</button>
      <button id="button9">Button 9</button>
    </div>
<!-- rest of code here -->
  </body>
</html>

On click, I want to:

  1. Retrieve the id of the button clicked (for further manipulation).
  2. Toggle the class to "active" for any of the buttons.

Instead of doing this:

$('#switcher').find('button').click(function(){
  var $element = $(this);      
  var elementid = this.id;
  $element.toggleClass('clicked');
  //rest of code here
});

I can either do this (Method 1)

$('#switcher').click(function(eventName){
  if ($(eventName.target).is('button')) {
    var $element =$(eventName.target);
    var elementid = eventName.target.id;
    $element.toggleClass('active');
    //rest of code here
  }
});

Or this (Method 2)

$('#switcher').on('click', 'button', function(){
  var $element = $(this);
  var elementid = this.id;
  $element.toggleClass('active');
  //rest of code here
});
  1. Are these 2 actually both delegation techniques?
  2. If so, Which of the two methods is faster (or better performance wise) and handles delegation better?
  3. Are there browser limitations?
  • 1
    You definitely should let jQuery handle the delegation for you. It's more complicated than `$(eventName.target).is('button')` – Bergi Oct 05 '16 at 15:46
  • 1
    Certainly, both methods do the same: attach an event handler to a single element. But I wouldn't skip the jQuery syntax sugar just for a negligible performance benefit. Good question anyway. – Álvaro González Oct 05 '16 at 15:51
  • 1
    I'd prefer method 2. – Daniel W. Oct 05 '16 at 15:51
  • 1
    Use whichever method is the right tool for the job. performance has little to do with it. – Kevin B Oct 05 '16 at 15:51
  • 1
    jQuery uses Method 2 in their docs: https://learn.jquery.com/events/event-delegation/ – mhodges Oct 05 '16 at 16:04
  • 2
    Method 1 and 2 are differents, the #1 doesn't handle case where your buttons contain other element (this is not your case but it could be...). The right check should be `if ($(eventName.target).closest('button').length)`. And regarding single click event, the only concer regarding performance should be time for maintanability. The speed performance has no meaning here – A. Wolff Oct 05 '16 at 16:04
  • `.on()` (with or without delegation) is also preferred because you can namespace your events and very easily `.off()` specific handlers. – mhodges Oct 05 '16 at 16:07
  • 2
    @demo Your example is not event delegation.. – mhodges Oct 05 '16 at 16:16
  • @demo **↑↑↑** and btw bind click event for each button, which regarding any processing performance is worst than proposed methods – A. Wolff Oct 05 '16 at 16:17
  • 1
    BTW, `$element.id` is unlikely to work. You'd want either `this.id` or `$element.attr('id')`. In Method 1, you need to use `var $element = $(eventName.target);` in order to call `toggleClass` on it. – Heretic Monkey Oct 05 '16 at 18:02
  • @MikeMcCaughan To cache the object, I passed `$(this)` to the variable `$element`. – Bashiru Ismail Babatunde Oct 05 '16 at 18:20
  • Right, but not in Method 1. And a jQuery object does not have a property `id`. – Heretic Monkey Oct 05 '16 at 18:21
  • Oh! Sorry, your comment was valid. I'll edit the question to reflect it. @MikeMcCaughan – Bashiru Ismail Babatunde Oct 05 '16 at 18:31

1 Answers1

0

In your very specific case, the two methods will offer the exact same functionality when clicking on a button element (on all browsers) and performance will be the same (since it is a click event, it would be a tiny difference and would also be difficult to test in an accurate way).

This is true for your particular structure:

<div id="switcher">
      <button id="button1">Button 1</button>
      <button id="button3">Button 2</button>
</div>

But if the DOM structure changes, only a little bit:

<div id="switcher">       
    <button id="button1">
        <div class="inner">Button 1</div>
    </button>
    <button id="button3">
        <div class="inner">Button 2</div>
    </button>
</div>

...then only the "official" jQuery event delegation will actually detect click events on all children.

If you already use jQuery in your page, hacking the event listener to emulate event delegation is useless. You won't get any advantage, apart from writing more code. Someone mentioned performance: forget it with click events. Useless optimisation is at least as bad as premature optimisation because it wastes your time and makes code less readable, but in this case it would not even be an optimisation (or it would be just a geek game to prove seriously).

Beware that click events rarely (or never?) represent a performance issue. They only happen once in a while. RequestAnimationFrame, scroll or resize can represent a problem, not clicks. The only case a click event could be a performance issue would be if you have an insanely (really extreme!) complex DOM structure: but in that case it would probably mean that you should fix that first.

taseenb
  • 1,378
  • 1
  • 16
  • 31
  • Actually, asides the minor error in the code which has been corrected, both methods will work for the example you gave. `.target` in `if($(eventName.target).is('button')) {` gets the exact element the click operation was carried out on regardless of if it is nested by any no of elements. As long as it is in under `
    `.
    – Bashiru Ismail Babatunde Oct 05 '16 at 18:42
  • 1
    sorry, my first example was actually slightly wrong. i fixed it. if you have an element inside the `button` then only the second method (jquery event delegation) will actually work. – taseenb Oct 06 '16 at 16:09