直接与委派 - jQuery .on()

moe*_*oey 157 javascript jquery event-bubbling event-binding jquery-events

我试图理解使用jQuery .on()方法直接委托事件处理程序之间的这种特殊区别.具体而言,本段最后一句:

selector被提供时,事件处理程序被称为委托.当事件直接发生在绑定元素上时,不会调用处理程序,但仅适用于与选择器匹配的后代(内部元素).jQuery将事件从事件目标起泡到附加处理程序的元素(即最里面到最外层的元素),并为匹配选择器的路径上的任何元素运行处理程序.

"运行任何元素的处理程序"是什么意思?我做了一个测试页面来试验这个概念.但是以下两个结构导致了相同的行为:

$("div#target span.green").on("click", function() {
   alert($(this).attr("class") + " is clicked");
});
Run Code Online (Sandbox Code Playgroud)

要么,

$("div#target").on("click", "span.green", function() {
   alert($(this).attr("class") + " is clicked");
});
Run Code Online (Sandbox Code Playgroud)

也许有人可以参考一个不同的例子来澄清这一点?谢谢.

N3d*_*st4 365

案例1(直接):

$("div#target span.green").on("click", function() {...});
Run Code Online (Sandbox Code Playgroud)

==嘿!我希望div#target中的每个span.green都能听到:当你点击它时,做X.

案例2(委托):

$("div#target").on("click", "span.green", function() {...});
Run Code Online (Sandbox Code Playgroud)

==嘿,div#target!当您点击任何"span.green"的子元素时,请使用它们执行X.

换一种说法...

在案例1中,每个跨度都已单独给出说明.如果创建了新跨度,他们将听不到指令,也不会响应点击.每个跨度直接负责自己的事件.

在案例2中,只有容器被给予指令; 它负责代表其子元素注意点击.捕获事件的工作已被委派.这也意味着将对将来创建的子元素执行该指令.

  • 这是一个很好的解释,并使我一直拒绝理解的问题变得清晰.谢谢! (44认同)
  • .on()是一个通用API,可以处理任何类型的事件,包括多个不同的事件(您可以在第一个字符串中放置多个事件名称.).click()只是第一个表单的简写. (5认同)
  • 那么为什么`on()`允许两个参数,这几乎与使用`click()`相同? (3认同)
  • @newbie,@N3dst4:“e.target”将是单击事件的初始目标(如果“span.green”有子节点,则可以是子节点)。在处理程序内部,您应该使用“this”引用。请参阅[这个小提琴](http://jsfiddle.net/LeGEC/JRHWX/1/)。 (2认同)

nnn*_*nnn 5

第一种方法是$("div#target span.green").on(),将单击处理程序直接绑定到执行代码时与选择器匹配的span.这意味着如果稍后添加其他跨度(或者将其类更改为匹配),则它们会错过并且不会有单击处理程序.这也意味着如果您稍后从其中一个跨度中删除"绿色"类,其单击处理程序将继续运行 - jQuery不会跟踪处理程序的分配方式,并检查选择器是否仍然匹配.

第二种方法是$("div#target").on(),将一个单击处理程序绑定到匹配的div(再次,这与那时匹配的div)相关联,但是当div中某处发生单击时,处理程序函数将仅在单击时运行不仅发生在div中,而且发生在与第二个参数中的选择器匹配的子元素.on()"span.green"中.通过这种方式完成这些子跨度的创建并不重要,点击它们仍将运行处理程序.

因此,对于不动态添加或更改其内容的页面,您不会注意到这两种方法之间的差异.如果您正在动态添加额外的子元素,则第二种语法意味着您不必担心为它们分配点击处理程序,因为您已经在父项上完成了一次.


Bry*_*ira 5

N3dst4的解释很完美。基于此,我们可以假设所有子元素都在 body 内部,因此我们只需要使用这个:

$('body').on('click', '.element', function(){
    alert('It works!')
});
Run Code Online (Sandbox Code Playgroud)

它适用于直接或委托事件。

  • jquery 建议不要使用 body,因为它比较慢,因为脚本必须搜索 body 内的所有孩子,这在大多数情况下应该很多。最好(更快)使用元素的中间父容器。 (2认同)
  • Jquery 删除了实时方法,该方法的作用与您所展示的相同。这是性能较弱的,不应该使用。 (2认同)