代表团做什么而不是简单的('点击',......)?

时间:2011-11-14 17:23:52

标签: jquery delegation jquery-1.7

这两种不同的jQuery语句的性能和处理有何不同:

  1. 排名第一

    $('#selector1, #selector2, .class1').on('click', function () { 
         //stuff
    });
    
  2. 第二名

    $(document).on('click', '#selector1, #selector2, .class1', function () { 
         //stuff
    });
    
  3. 我知道一个人做代表团而另一个人没有代表团。

    但这意味着什么?

    点击'#selector1, #selector2, .class1'时,不要两者都采取某种行动吗?

    最后,是不是一样?

4 个答案:

答案 0 :(得分:8)

Number One会在执行该语句时将click事件挂钩到存在的元素上。例如,处理程序直接挂钩到执行该调用时匹配的实际元素。

第二个会将click事件挂钩到文档上,并且在收到任何点击后,将检查实际点击的元素是否与任何给定的选择器匹配,如果是,则触发处理程序。这是事件委托而不是直接连接。

所以这意味着几件事:

  1. 使用第二个,点击您稍后添加的元素将触发处理程序;第一,他们不会。
  2. 只有像click这样的冒泡事件才能与第二号一起工作(因为它依赖于将DOM冒泡到文档级别的事件)。
  3. 如果您使用委托处理程序(第二个)并且某些其他代码将事件挂接到实际元素上,然后取消事件的传播(冒泡),则委派的处理程序将不会看到它。
  4. 委派表单(第二个)必须匹配单击发生时单击的元素(可能是其祖先),这需要非零时间。不一定很多时间,但不仅仅是直接处理程序(不必这样做)。如果你在同一个元素上有很多委托处理程序(在本例中是文档),你可能会开始注意到。
  5. 有时候使用直接挂钩的处理程序会更好,而事件委派(通常使用比document更集中的东西)的时候更好。通常,它们之间的分界线是一个判断调用,但是例如,如果你想响应表行的点击,你可能最好用click元素挂钩table事件。 tr选择器,而不是附加每个表行的click事件,尤其是在动态更新表时。然而,如果你有一个独特的按钮,当你正在连接你的处理程序时你知道它存在于DOM中,并且当你想要在点击该按钮(但不是其他任何东西)时触发特定的函数,直接处理程序可能更有意义。

    以下是一个示例(live copy):

    HTML:

    <p>Click me</p>
    

    JavaScript的:

    jQuery(function($) {
    
      $('p').on('click', function() {
        display("Directly-attached handler fired. Click this paragraph and note the difference in what happens compared to when you click the 'click me' paragraph.");
      });
      $(document).on('click', 'p', function() {
        display("Delegated handler fired.");
      });
    
      function display(msg) {
        $("<p>").html(msg).appendTo(document.body);
      }
    });
    

    请注意,当您单击“单击我”段落时,您会在文档中添加两个新段落,其中一个是第一个on调用的结果,另一个是第二个调用的结果。但请注意,如果您单击这两个新段落中的任何一个,则会从第二个on调用(委派的一个)中查看处理程序,而不是第一个。那是因为当你连接第一个处理程序时,那些段落不存在。

答案 1 :(得分:5)

  1. on()方法为jQuery对象匹配的每个元素附加一个事件处理程序。如果将可选选择器传递给on()方法,则只有在该元素的后代发生事件时才会触发处理程序。

    因此,第一个示例将附加多个事件处理程序,因为jQuery对象包含3个元素。但是,第二个示例将附加一个事件处理程序,它将处理所有'#selector1, #selector2, .class1'

    的click事件

    显然,如果匹配了许多元素,则第一个处于性能劣势(因为绑定了多个事件处理程序,与第二个示例中附加的单个事件处理程序相比)。

    对于少量对象,选择第一个示例优先于微优化。但是,如果你有很多元素(列表项,表中的行),你应该认真考虑使用第二个例子。

  2. 因为on()将处理程序附加到jQuery对象匹配的每个元素,所以不能将处理程序直接附加到尚未包含在DOM中的元素(例如,如果您希望通过编程方式添加元素代码或通过AJAX)。这就是将选择器作为参数提供给on()的能力变得非常非常有用;这允许您将事件处理程序附加到当前在DOM中的元素,但是它将处理触发DOM中尚未但与您提供的选择器匹配的元素的事件

    换句话说,在第一个示例中,jQuery将事件处理程序附加到与#selector1, #selector2, .class1选择器匹配的所有元素;所以会遗漏尚未在DOM中注册的所有元素。

    另一方面,如果您使用第二个示例,jQuery会将事件处理程序附加到与document选择器匹配的所有元素(例如单个Document元素),并为其附加处理程序如果它收到的事件来自选择器#selector1, #selector2, .class1匹配的元素,它将触发;这有利于所有未来的#selector1, #selector2, .class1元素。

    你可以在这里看到这个; http://jsfiddle.net/kntR7/

  3. 因为第二个绑定到document,所以接受同一事件的处理程序的任何元素都将在之前接收处理程序(因为document是通过接收处理程序的最后一个位置事件传播),因此,如果它选择使用event.stopPropagation()event.stopImmediatePropagation()取消事件,则永远不会到达处理程序。

    你可以在这里看到这个; http://jsfiddle.net/mkNyU/

答案 2 :(得分:1)

对于熟悉1.7之前语法的人,以下是on的使用方法:

//bind syntax
$(selector).on(event, callback);
$(selector).bind(event, callback);

//delegate syntax
$(parent).on(event, selector, callback);
$(selector).delegate(selector, event, callback);

//live syntax
$(document).on(event, selector, callback);
$(selector).live(event, callback);

因此,您的第一行($('#selector1, #selector2, .class1').on('click', function))是bind格式,用于将事件附加到现有元素。

您的第二行($(document).on('click', '#selector1, #selector2, .class1', function))是一种live格式,用于在事件发生时将事件附加到与选择器匹配的任何元素,无论绑定时元素是否存在于dom中

答案 3 :(得分:0)

第一个绑定3+事件处理程序(每个元素一个),一旦元素被替换就会丢失。如果元素尚不存在,第一个将失败。

第二个绑定1个事件处理程序(一个到document)除非您明确删除它,否则永远不会丢失。一旦在此处调用处理程序,该事件就已传播到document。无论何时单击页面上的任何位置,jQuery都会在内部检查它是否在与您提供的选择器匹配的任何元素上,并触发您提供的处理程序。仅当事件传播到document并且未在较低级别元素处停止时才会这样。

第二个可以在文档就绪之前绑定,即使元素不存在它仍然可以工作。