jQuery中的事件委托 - 哪种方法更好?

4
为了编写更好的代码并改进我对jQuery的使用,最近我一直在阅读相关资料。其中一个新的技巧是使用jQuery事件委托。
在阅读过程中,我发现有两种“所谓”的不同方法来解决它。下面是代码片段以说明它们。
假设我有一个像这样的HTML块:
<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>

点击时,我希望能够:

  1. 获取被点击按钮的id(以便进一步操作)。
  2. 为任何一个按钮切换“active”类。

不要这样做:

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

我可以选择这种方法(方法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
  }
});

或者这样做(方法2)
$('#switcher').on('click', 'button', function(){
  var $element = $(this);
  var elementid = this.id;
  $element.toggleClass('active');
  //rest of code here
});
  1. 这两种技术都是委托技术吗?
  2. 如果是的话,哪一种方法更快(或者性能更好)并且处理委托更好呢?
  3. 是否存在浏览器限制?

1
当然,这两种方法都是一样的:将事件处理程序附加到单个元素。但是我不会仅仅为了微不足道的性能提升而跳过jQuery语法糖。无论如何,这是一个好问题。 - Álvaro González
1
我更喜欢方法2。 - Daniel W.
1
使用正确的工具来完成工作,性能与此无关。 - Kevin B
2
方法1和方法2是不同的,#1不能处理按钮包含其他元素的情况(虽然这不是你的情况,但它可能会出现...)。正确的检查应该是if ($(eventName.target).closest('button').length)。至于单击事件,唯一需要关注的是可维护性所需的时间,速度性能在这里没有意义。 - A. Wolff
2
@demo 您的示例不是事件委托。 - mhodges
显示剩余8条评论
1个回答

0
在您的特定情况下,当单击元素时(在所有浏览器上),这两种方法将提供完全相同的功能,并且性能也将相同(因为它是一个点击事件,差异很小,而且也很难以准确的方式进行测试)。
对于您特定的结构,这是正确的:
<div id="switcher">
      <button id="button1">Button 1</button>
      <button id="button3">Button 2</button>
</div>

但是如果DOM结构发生了一点变化:

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

...那么只有“官方”的jQuery事件委托才能实际检测所有子元素的点击事件。

如果您已经在页面中使用了jQuery,则对事件侦听器进行黑客攻击以模拟事件委托是无用的。除了编写更多代码之外,您不会获得任何优势。有人提到性能:忘记它与单击事件一起使用。无用的优化至少和过早的优化一样糟糕,因为它浪费了您的时间并使代码变得不太可读,但在这种情况下,它甚至不会是一种优化(或者只是一个极客游戏来证明严肃)。

请注意,单击事件很少(或从未?)表示性能问题。它们只偶尔发生。请求动画帧、滚动或调整大小可能会导致问题,而不是单击。唯一的情况是,如果您有一个极其(真正极端!)复杂的DOM结构,单击事件可能会成为性能问题:但在这种情况下,这可能意味着您应该首先解决这个问题。


实际上,在代码中已经修正了的小错误之外,你给出的例子两种方法都可以工作。在 if($(eventName.target).is('button')) { 语句中的 .target 可以获取到点击操作所针对的元素,无论它是否被任何数量的元素嵌套。只要它在 <div id="switcher"> 下就可以。 - Bashiru Ismail Babatunde
1
抱歉,我的第一个示例实际上略有错误。我已经修复了它。如果您在button内部有一个元素,则只有第二种方法(jQuery事件委托)才能正常工作。 - taseenb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接