4

这两个不同的 jQuery 语句的性能和处理有什么不同:

  1. 一号

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

    $(document).on('click', '#selector1, #selector2, .class1', function () { 
         //stuff
    });
    

我知道一个做委托,另一个不做。

但是,这是什么意思?

当您单击 时,两者都不会执行某种操作'#selector1, #selector2, .class1'吗?

最后,不都是一样的吗?

4

4 回答 4

8

第一个将在您执行该语句时将事件挂钩到click存在的元素上。例如,当您执行该调用时,处理程序直接连接到匹配的实际元素。

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

所以这意味着几件事:

  1. 使用第二个,单击稍后添加的元素将触发处理程序;第一,他们不会。
  2. 只有冒泡事件才能click与 Number Two 一起使用(因为它依赖于将 DOM 冒泡到文档级别的事件)。
  3. 如果您使用委托处理程序(第二个)并且其他一些代码将事件挂钩到实际元素上,然后取消事件的传播(冒泡),则委托处理程序将看不到它。
  4. 当点击发生时,委托表单(第二个)必须将被点击的元素(可能还有它的祖先)与选择器匹配,这需要非零的时间。不一定需要很多时间,但比直接处理程序(不必这样做)要多。如果您在同一个元素(在本例中为文档)上有很多委托处理程序,您可能会开始注意到这一点。

有时使用直接挂钩的处理程序更好,有时事件委托(通常使用比 更集中的东西document)更好。通常,它们之间的分界线是判断调用,但例如,如果您想响应对表格行的点击,您最好使用选择器将click事件挂钩到table元素上tr,而不是附加每个click事件表行,特别是如果您动态更新表。然而,如果您在连接处理程序时知道 DOM 中存在一个唯一按钮,并且您希望在单击该按钮(但不是其他任何内容)时触发特定功能,那么直接处理程序可能更有意义。

这是一个示例(实时副本):

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调用(委托的)中的处理程序,而不是第一次。那是因为当您连接第一个处理程序时,这些段落不存在。

于 2011-11-14T17:27:00.100 回答
4
  1. on()方法为 jQuery 对象匹配的每个元素附加一个事件处理程序。如果您将可选选择器传递给on()方法,则仅当事件发生在该元素的后代上时,处理程序才会触发。

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

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

    对于少数对象,选择第二个示例而不是第一个示例充其量是微优化。但是,如果您有很多元素(列表项、表格中的行),您应该认真考虑使用第二个示例而不是第一个示例。

  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()or取消事件event.stopImmediatePropagation(),则处理程序将永远无法到达。

    您可以在此处查看此操作;http://jsfiddle.net/mkNyU/

于 2011-11-14T17:27:39.583 回答
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 中。

于 2011-11-14T17:32:05.533 回答
0

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

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

第二个甚至可以在文档准备好之前绑定,即使元素还不存在,它仍然可以工作。

于 2011-11-14T17:31:32.313 回答