jQuery .on()委托,它的选择器与嵌套元素匹配

问题描述 投票:1回答:3

// 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()行为,它将变得更加疯狂。您实际上可以避免第二次执行,尽管事件已经到达#delegatestopPropagation(不应在这里工作。

在执行委派逻辑时会执行哪种“魔术”?事件冒泡和程序流是否以任何方式分开?

请首先不要发布“实用建议”(“请改用xyz!”)。我想了解为什么代码会按其方式工作。

javascript jquery jquery-events delegation event-bubbling
3个回答
0
投票

由于您通过两种方式在所有div上绑定了事件:

  1. 使用元素div的id属性。
  2. 使用元素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>

事件委托的工作方式是jQuery将DOM树从最内层的目标移动到委托所绑定的元素,测试每个元素以查看其是否与选择器匹配。如果是这样,它将使用绑定到该元素的this执行处理程序。

当调用event.stopPropagation时,它将在event对象中设置一个标志。遍历DOM树的循环也称为event.isPropagationStopped()。如果传播停止,它将退出循环。

换句话说,jQuery在实现委派时会自行执行冒泡并停止传播,它没有利用浏览器的冒泡(除非这种冒泡对于在#delegate上触发初始事件是必要的,所以jQuery循环将运行)。

一切正常。看看this fiddle

$("#delegate").on("click", "div", function(event) {
  // event.stopPropagation();
  alert('div: ' + $(this).attr('id'));
});

单击#inner将触发上述事件。由于#outer#inner的后代,因此事件将上升到#outer。由于#outer也是<div,因此事件也会在#outer上触发。逻辑上,单击#inner将首先警告“ div:内部”,然后警告“ div:内部”。

呼叫event.stopPropagation()会告诉事件不要冒泡,因此#outer不会被调用。

[C0中以外:

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不是父母,而是同级。


0
投票

事件委托的工作方式是jQuery将DOM树从最内层的目标移动到委托所绑定的元素,测试每个元素以查看其是否与选择器匹配。如果是这样,它将使用绑定到该元素的this执行处理程序。


0
投票

一切正常。看看this fiddle

© www.soinside.com 2019 - 2024. All rights reserved.