为什么event.stopPropagation()会停止委派事件中的多个匹配元素
Why does event.stopPropagation() stop multiple matched elements in delegated events?
使用委托事件时,所有匹配的元素都会在事件从目标弹出时触发该事件。
基于https://learn.jquery.com/events/event-delegation/参考下面的HTML和JS,点击div four会在它冒泡时触发所有祖先(div一、div二、div三、body)的点击事件。我将事件处理程序放在主体上,选择:not(#div-three)
这可以在https://jsfiddle.net/bLw7ch50/1/例如,单击div 4会触发3个警报。对于div四,div二和div一。
我认为发生的事情是这样的:
- 点击
div-four
,点击div-four
触发的事件 div-four
事件气泡到div-three
,点击div-three
事件触发div-four
事件气泡到div-two
,点击div-two
事件触发div-four
事件气泡到div-one
,点击div-one
事件触发div-four
事件气泡到body
,点击事件从body
触发。事件处理程序运行。报告target:div-four|current:div-four
div-three
(来自步骤2)事件冒泡到body
。不触发事件处理程序- CCD_ 19(来自步骤3)事件气泡到CCD_ 20。事件处理程序运行。报告
target:div-four|current:div-two
- CCD_ 22(来自步骤4)事件气泡到CCD_ 23。事件处理程序运行。报告
target:div-four|current:div-one
如果在事件处理程序中调用了event.stopPropagation()
,则div-four
事件在步骤5停止冒泡。(尽管在body
上方无论如何都没有气泡。)然而,步骤2、3、4中触发的事件应该仍然存在并气泡上升,因此步骤6、7、8仍将继续。
然而,情况似乎并非如此。在以下内容中https://jsfiddle.net/bLw7ch50/,取消对event.stopPropagation()
的注释后,仅显示1个警报,即target:div-four|current:div-four
。所以我可能在某个地方错了。我的理解有什么问题?
HTML:
<body>
<div id="div-one">
1st div
<div id="div-two">
2nd div
<div id="div-three">
3rd div
<div id="div-four">
4th div
</div>
</div>
</div>
</div>
<br/>
<br/>
<div id="output">
</div>
</body>
CSS:
div {
border: 1px solid;
}
Javascript(带jquery1.9.1)
$(document).ready(function() {
$("body").on("click", ":not(#div-three)", function(event) {
var event_target = $(event.target).attr("id");
var event_current = $(event.currentTarget).attr("id");
$("#output").append("target:" + event_target +
"|current:" + event_current + "<br/>");
alert("target:" + event_target +
"|current:" + event_current);
// Commented out in https://jsfiddle.net/bLw7ch50/1/, exists in https://jsfiddle.net/bLw7ch50
event.stopPropagation(); // When this line is here, all other events stop
});
});
这一切都发生在jQuery的事件委派中,除了jQuery试图模仿正常事件之外,它与事件气泡的方式无关。
使用普通的事件处理程序,如果stopPropagation
,则该事件将不再出现在树中,并且具有相同事件类型的处理程序的祖先将不会接收到它。这与在使用事件委派时用于决定是否应为元素调用事件处理程序的逻辑相同。
使用委派绑定事件时,只将一个事件绑定到委派目标。当触发事件处理程序(不是您的事件处理程序,而是jQuery的内部处理程序)时,jQuery会查看原始事件目标和委托目标之间的元素,然后根据选择器筛选这些元素,并按从原始事件目标到委托目标的顺序调用它们上的处理程序。如果这些处理程序中的任何一个stopPropagation
,则合格事件目标列表中的任何其他元素都不会调用该处理程序。在此过程中不会触发其他事件。
该系统还考虑了其他委托事件。
$(document).on('click', '.box1', function () {
console.log('first box1 handler');
});
$(document).on('click', '.box1', function (e) {
console.log('second box1 handler');
e.stopPropagation();
});
$(document).on('click', '.box2', function () {
console.log('first box2 handler');
});
$(document).on('click', '.box2', function (e) {
console.log('second box2 handler');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="box1">
<div class="box1">
<div class="box1">
<div class="box1">
click here to begin
</div>
</div>
</div>
</div>
<div class="box2">
<div class="box2">
<div class="box2">
<div class="box2">
click here to begin without propagation
</div>
</div>
</div>
</div>
如果您单击第一个框,您将只调用第一个处理程序和第二个处理程序一次,因为我们停止了在最里面的div上传播。这两个处理程序仍然被调用,因为我们使用了stopPropgation
而不是stopImmediatePropagation
。如果单击第二个,两个处理程序将按正确顺序为每个boxdiv调用一次。
不幸的是,我找不到任何支持这一点的文档。
- 元素事件处理程序到EXT.js面板中
- 浏览器中的javascript和td元素事件属性
- 主干清理元素事件
- 影响类的所有成员而不是一个元素事件的插件正在发生
- AngularJS - ngRepeat.在 ng 重复重新渲染后,需要将焦点集中在相同的元素事件上
- 在jQuery中,如何触发mootools中添加的元素事件
- 允许 Raphael/SVG 元素事件通过顶部分层的 HTML 触发
- CanJS未来元素事件绑定
- 重新选择所选选项时,Javascript/jQuery选择元素事件
- 类变量在元素事件中不可见
- 修改元素'事件函数的参数
- 如何过滤掉事件处理程序中的子元素事件
- 要求Javascript关注多个元素事件的模式
- 允许先触发其他绑定元素事件
- Firefox扩展不能覆盖元素事件
- 如何获取"mouseup"之后的元素事件完成
- 用于文档防止元素事件的Onclick事件
- 如何获取触发“onclick”的元素事件
- 向由子元素事件触发的表单元格添加类/从中删除类
- JavaScript在元素加载后立即绑定元素事件