// Example A
$("#delegate").on("click", function(event) {
// executes on click on any descendant of #delegate or self (not a delegate at all)
// 'this' is #delegate
});
// Example B
$("#delegate").on("click", "#outer", function(event) {
// executes on click on any descendant of #outer or self
// 'this' is #outer or #inner (depends on the actual click)
});
$("#delegate").on("click", "#inner", function(event) {
// executes on click on any descendant of #inner or self (nothing happens when clicking #outer)
// 'this' is #inner
});
// Example C (now it's getting weird)
$("#delegate").on("click", "div", function(event) {
// executes twice, when clicking #inner, because the event passes #outer when bubbling up
// one time 'this' is #inner, and the other time 'this' is #outer
// stopPropagation() // actually prevents the second execution
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="delegate">
<div id="outer">
outer
<div id="inner">
inner
</div>
</div>
</div>
您如何在逻辑上解释此行为?
只有一个点击事件,从#inner开始,通过#outer冒泡,最后到达#delegate。
#delegate的on-handler将事件(确切地)捕获一次。处理程序检查事件的历史记录是否包含任何div元素。
如果适用,则应调用一次回调函数。这就是我所期待的。 “单个事件,单个处理程序,单个条件,单个回调”。
如果你看一下stopPropagation()行为,会变得更加疯狂。尽管事件已经到达#delegate,但你实际上可以避免这种情况。 stopPropagation()不应该在这里工作。
在授权逻辑的实现中做了什么样的“魔术”?事件冒泡和程序流程是否以任何方式分离?
感谢您对德国的解释和问候。 ; - )
请不要首先发布“实用建议”(“使用xyz代替!”)。我想了解为什么代码按照它的方式工作。
答案 0 :(得分:0)
因为你以两种方式绑定所有div上的事件:
所以,如果您event.stopPropagation();
在最后一个警告上,那么警报将会出现两次,因为您已经使用了div而且还有#inner
(例如。)
检查下面的代码段。
$("#delegate").on("click", function(event) {
alert(this.id);
});
/*
$("#delegate").on('click', "#outer", function(event) {
alert(this.id);
});
$("#delegate").on('click', "#inner", function(event) {
alert(this.id);
});
*/
// now it's getting weird
$("#delegate").on("click", "div", function(event) {
event.stopPropagation();
alert(this.id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="delegate">
<div id="outer">
outer
<div id="inner">
inner
</div>
</div>
</div>
答案 1 :(得分:0)
事件委托的工作方式是jQuery将DOM树从最里面的目标移动到委托绑定的元素,测试每个元素以查看它是否与选择器匹配。如果是,则执行绑定到该元素的this
处理程序。
调用event.stopPropagation
时,它会在event
对象中设置一个标志。遍历DOM树的循环也调用event.isPropagationStopped()
。如果传播停止,它就会脱离循环。
换句话说,jQuery在实现委托时正在进行自己的冒泡和传播停止,它没有利用浏览器的冒泡(除了这个冒泡对于初始事件是必要的在#delegate
上触发,以便jQuery循环运行。)
答案 2 :(得分:0)
一切都按预期工作。看看this fiddle:
$("#delegate").on("click", "div", function(event) {
// event.stopPropagation();
alert('div: ' + $(this).attr('id'));
});
点击#inner
会触发上述事件。由于#outer
是#inner
的后代,因此该事件将冒出#outer
。由于#outer
也是<div
,因此该事件也会在#outer
上触发。从逻辑上讲,点击#inner
将首先警告&#34; div:inner&#34;然后&#34; div:外部&#34;。
调用event.stopPropagation()
告诉事件不要冒泡,因此#outer
保持不受欢迎。
除了this fiddle:
<div id="delegate">
<div id="first">
first
</div>
<div id="second">
second
<div id="third">
third, inside second
</div>
</div>
</div>
点击第三个会先提醒third
,然后提醒second
,然后停止,因为#first
不是父母,而是兄弟。