什么之间的区别event.stopPropagation()
和event.stopImmediatePropagation()
?
stopPropagation 与 stopImmediatePropagation
stopPropagation
将防止任何父被执行的处理程序stopImmediatePropagation
将防止任何父处理程序,并且还任何其他处理程序从执行
jquery 文档中的快速示例:
$("p").click(function(event) {
event.stopImmediatePropagation();
});
$("p").click(function(event) {
// This function won't be executed
$(this).css("background-color", "#f00");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>example</p>
请注意,事件绑定的顺序在这里很重要!
一个小例子来演示这两种传播停止是如何工作的。
绑定了三个事件处理程序。如果我们不停止任何传播,那么应该有四个警报——三个在子 div 上,一个在父 div 上。
如果我们阻止事件传播,那么将会有 3 个警报(都在内部子 div 上)。由于该事件不会向上传播 DOM 层次结构,父 div 不会看到它,它的处理程序也不会触发。
如果我们立即停止传播,那么只会有 1 个警报。即使有 3 个事件处理程序附加到内部子 div,也只执行 1 个事件处理程序并且任何进一步的传播都会立即终止,即使在同一个元素中也是如此。
令人惊讶的是,所有其他答案只说了一半的事实或实际上是错误的!
e.stopImmediatePropagation()
停止为此事件调用任何进一步的处理程序,没有例外e.stopPropagation()
是相似的,但确实还呼吁所有的处理程序这一阶段对这个元素如果不是已经叫
什么阶段?
例如,一个点击事件总是首先沿着 DOM 向下(称为“捕获阶段”),最后到达事件的起点(“目标阶段”),然后再次冒泡(“冒泡阶段”)。并且addEventListener()
您可以独立地为捕获和冒泡阶段注册多个处理程序。(目标阶段在不区分的情况下调用目标上的两种类型的处理程序。)
这就是其他答案不正确的地方:
- 引用:“event.stopPropagation() 允许执行同一元素上的其他处理程序”
- 更正:如果在捕获阶段停止,将永远不会到达气泡阶段处理程序,也会在同一元素上跳过它们
- 引用:“event.stopPropagation() [...] 仅用于停止其相应父处理程序的执行”
- 更正:如果在捕获阶段停止传播,则不会调用任何孩子的处理程序,包括目标,不仅是父母
- ...并且:如果在冒泡阶段停止传播,则所有捕获阶段处理程序都已被调用,包括父级的处理程序
除了阻止执行元素上的任何其他处理程序之外,此方法还通过隐式调用 event.stopPropagation() 来停止冒泡。为了简单地防止事件冒泡到祖先元素但允许其他事件处理程序在同一元素上执行,我们可以使用 event.stopPropagation() 代替。
使用 event.isImmediatePropagationStopped() 了解是否曾经调用过此方法(在该事件对象上)。
简而言之:event.stopPropagation()
允许执行同一元素上的其他处理程序,同时event.stopImmediatePropagation()
阻止每个事件运行。
我是后来者,但也许我可以用一个具体的例子来说明这一点:
假设您有<table>
, 和<tr>
, 然后<td>
。现在,让我们说你设置3个的事件处理程序<td>
元素,那么如果你event.stopPropagation()
在你设定的第一个事件处理程序<td>
,则所有事件处理程序<td>
仍在运行,但该事件是不会传播到<tr>
或<table>
(并不会上升到<body>
, <html>
, document
, 和window
)。
但是现在,如果你使用event.stopImmediatePropagation()
你的第一个事件处理程序,那么,对于其他两个事件处理程序<td>
将不会运行,并且不会传播到<tr>
,<table>
(并不会上去达<body>
,<html>
,document
,和window
)。
请注意,它不仅适用于<td>
. 对于其他元素,将遵循相同的原则。