我试图理解使用jQuery .on()方法的直接和委托事件处理程序之间的特殊区别。具体来说,这段话的最后一句话:
当提供selector
时,事件处理程序被称为委托的。当事件直接发生在绑定元素上时,不会调用处理程序,而只会调用与选择器匹配的后代(内部元素)。jQuery将事件从事件目标冒泡到附加处理程序的元素(即,最里面的元素到最外面的元素),并在匹配选择器的路径上为任何元素运行处理程序。
"运行任何元素的处理程序"是什么意思?我制作了一个测试页面来试验这个概念。但是下面两个结构导致相同的行为:
$("div#target span.green").on("click", function() {
alert($(this).attr("class") + " is clicked");
});
或
$("div#target").on("click", "span.green", function() {
alert($(this).attr("class") + " is clicked");
});
也许有人可以参考一个不同的例子来澄清这一点?谢谢。 案例1(直接):
$("div#target span.green").on("click", function() {...});
= =嘿!我想要每个张成的空间。当你被点击时,做x
案例2(委托):
$("div#target").on("click", "span.green", function() {...});
==嘿,div#target!当你的任何子元素都是span。绿色"被点击,用它们做X。
换句话说
在情形1中,每个span都被单独给定了指令。如果创建了新的跨度,它们不会听到指令,也不会响应点击。每个span 直接对自己的事件负责。
在情形2中,只有容器收到了指令;它负责注意代表子元素的点击。捕获事件的工作已经委托给了。这也意味着该指令将对将来创建的子元素执行。
第一种方法是$("div#target span.green").on()
,在执行代码时将一个click处理程序直接绑定到与选择器匹配的span(s)。这意味着,如果稍后添加其他span(或将其类更改为匹配),它们就会错过,并且不会有click处理程序。这也意味着,如果你以后从一个span中删除了"green"类,它的点击处理程序将继续运行——jQuery不会跟踪处理程序是如何分配的,也不会检查选择器是否仍然匹配。
第二种方式,$("div#target").on()
,将点击处理程序绑定到匹配的div(再次,这是针对那些在那一刻匹配的),但是当点击发生在div中的某个地方时,处理程序函数将只在单击不仅发生在div中,而且发生在与第二个参数中的选择器匹配的子元素中.on()
,"span.green"时运行。通过这种方式创建这些子跨度并不重要,单击它们仍然会运行处理程序。
所以对于不动态添加或更改其内容的页面,您不会注意到这两个方法之间的区别。如果您动态添加额外的子元素,第二种语法意味着您不必担心为它们分配单击处理程序,因为您已经在父元素上完成了一次。
N3dst4的解释是完美的。基于此,我们可以假设所有子元素都在body内部,因此我们只需要使用this:
$('body').on('click', '.element', function(){
alert('It works!')
});
它与直接或委托事件一起工作。
与OP无关,但帮助我解开此功能困惑的概念是绑定元素必须是所选元素的父元素。
- Bound指的是
.on
的剩余部分。 - 选中为
.on()
的第二个参数。
委托不像.find()那样选择绑定元素的子集。选择器只适用于严格的子元素。
$("span.green").on("click", ...
与
非常不同$("span").on("click", ".green", ...
特别是,为了获得@N3dst4提示的"将来创建的元素"的优势,绑定元素必须是永久父元素。然后选定的孩子可以来和去。
编辑委派.on
不起作用的原因清单
$('.bound').on('event', '.selected', some_function)
可能无法工作的棘手原因:
- 绑定元素不是永久的。它是在调用
.on()
之后创建的 - 所选元素不是绑定元素的子元素。这是相同的元素。
- 选定元素通过调用
.stopPropagation()
阻止冒泡事件到绑定元素。
(省略不太棘手的原因,例如拼写错误的选择器)
我写了一篇文章,比较了直接事件和委托事件。我比较纯js,但它有相同的含义为jquery只是封装它。
结论是,委托事件处理是动态DOM结构,绑定元素可以在用户与页面交互时创建(不需要再次绑定),而直接事件处理是静态DOM元素,当我们知道结构不会改变。
查看更多信息和完整比较http://maciejsikora.com/standard-events-vs-event-delegation/
始终使用委托处理程序,我认为这是目前非常流行的不是正确的方式,许多程序员使用它是因为"它应该被使用",但事实是,直接事件处理程序在某些情况下更好,使用哪种方法应该由差异知识支持。
案例3(委托):
$("div#target").delegate("span.green", "click", function() {...});