首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么event.stopPropagation()在委托事件中停止多个匹配的元素?

为什么event.stopPropagation()在委托事件中停止多个匹配的元素?
EN

Stack Overflow用户
提问于 2016-08-04 17:18:50
回答 1查看 1K关注 0票数 0

当使用委托事件时,所有匹配的元素都会在事件从目标中冒泡时触发事件。

基于https://learn.jquery.com/events/event-delegation/并引用下面的HTML和JS,单击div-4触发器,在其所有祖先(div-1、div-2、div-3、body)上单击事件。我将事件处理程序放在body上,为:not(#div-three)选择

https://jsfiddle.net/bLw7ch50/1/中可以看到这一点,例如单击div 4会触发3个警报。第四,第二和第一。

我想发生的事情是这样的:

  1. 单击div-four,单击div-four触发的事件。
  2. div-four事件冒泡为div-three,单击div-three触发的事件。
  3. div-four事件冒泡为div-two,单击div-two触发的事件。
  4. div-four事件冒泡为div-one,单击div-one触发的事件。
  5. div-four事件冒泡为body,单击body触发的事件。事件处理程序运行。报告target:div-four|current:div-four
  6. div-three (来自step2)事件气泡一直持续到body。不触发事件处理程序。
  7. div-two (从step3)事件气泡到body。事件处理程序运行。报告target:div-four|current:div-two
  8. div-one (从step4)事件气泡到body。事件处理程序运行。报告target:div-four|current:div-one

如果在事件处理程序中调用了一个event.stopPropagation(),那么div-four事件将在步骤5停止冒泡(尽管在body之上没有什么可以冒泡的)。然而,在步骤2、3、4中触发的事件应该仍然存在,并出现泡影,因此步骤6、7、8仍将继续。

然而,情况似乎并非如此。在下面的https://jsfiddle.net/bLw7ch50/中,在取消注释event.stopPropagation()之后,只会出现一个警报target:div-four|current:div-four。所以我可能在哪里错了。我的理解怎么了?

HTML:

代码语言:javascript
复制
<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:

代码语言:javascript
复制
div {
  border: 1px solid;
}

Javascript (使用jquery1.9.1)

代码语言:javascript
复制
$(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
  });
});
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-08-04 18:21:46

这一切都发生在jQuery的事件委托中,除了jQuery试图模仿正常事件发生的方式之外,它与事件气泡的方式无关。

对于普通的事件处理程序,如果您stopPropagation该事件将不再在树上冒泡,而具有相同事件类型的处理程序的祖先将不会接收它。这是用于决定在使用事件委托时是否应该为元素调用事件处理程序的相同逻辑。

使用委托绑定事件时,只将一个事件绑定到委托目标。当事件处理程序(不是您的事件处理程序,jQuery的内部处理程序)被触发时,jQuery会查看原始事件目标和委托目标之间的元素,然后根据选择器过滤那些元素,然后根据从原始事件目标到委托目标的顺序调用它们上的处理程序。如果其中任何一个处理程序是stopPropagation,那么在符合条件的事件目标列表中的其他元素都不会被调用。在此过程中不会触发其他事件。

该系统还考虑到其他委托事件。

代码语言:javascript
复制
$(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');
});
代码语言:javascript
复制
<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,所以仍然会调用它们。如果单击第二个,两个处理程序都将按正确的顺序为每个方框div调用一次。

不幸的是,我找不到任何文件来支持这一点。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38773687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档