【发布时间】:2011-07-15 01:24:42
【问题描述】:
event.stopPropagation() 和 event.stopImmediatePropagation() 有什么区别?
【问题讨论】:
-
我鼓励读者不仅要坚持接受的答案,还要阅读其他答案,尤其是罗伯特·西默 (Robert Siemer) 的非常有启发性的答案。需要很好地了解传播的工作原理才能很好地理解它。
标签: javascript jquery
event.stopPropagation() 和 event.stopImmediatePropagation() 有什么区别?
【问题讨论】:
标签: javascript jquery
stopPropagation 将阻止任何 父 处理程序执行 stopImmediatePropagation 将阻止任何父处理程序 以及 任何 其他 处理程序执行
来自jquery documentation: 的快速示例
$("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>
注意这里事件绑定的顺序很重要!
$("p").click(function(event) {
// This function will now trigger
$(this).css("background-color", "#f00");
});
$("p").click(function(event) {
event.stopImmediatePropagation();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>example</p>
【讨论】:
一个小例子来演示这两种传播停止是如何工作的。
var state = {
stopPropagation: false,
stopImmediatePropagation: false
};
function handlePropagation(event) {
if (state.stopPropagation) {
event.stopPropagation();
}
if (state.stopImmediatePropagation) {
event.stopImmediatePropagation();
}
}
$("#child").click(function(e) {
handlePropagation(e);
console.log("First event handler on #child");
});
$("#child").click(function(e) {
handlePropagation(e);
console.log("Second event handler on #child");
});
// First this event will fire on the child element, then propogate up and
// fire for the parent element.
$("div").click(function(e) {
handlePropagation(e);
console.log("Event handler on div: #" + this.id);
});
// Enable/disable propogation
$("button").click(function() {
var objectId = this.id;
$(this).toggleClass('active');
state[objectId] = $(this).hasClass('active');
console.log('---------------------');
});
div {
padding: 1em;
}
#parent {
background-color: #CCC;
}
#child {
background-color: #000;
padding: 5em;
}
button {
padding: 1em;
font-size: 1em;
}
.active {
background-color: green;
color: white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<div id="child"> </div>
</div>
<button id="stopPropagation">Stop Propogation</button>
<button id="stopImmediatePropagation" ">Stop Immediate Propogation</button>
绑定了三个事件处理程序。如果我们不停止任何传播,那么应该有四个警报 - 三个在子 div 上,一个在父 div 上。
如果我们阻止事件传播,那么将有 3 个警报(全部在内部子 div 上)。由于事件不会向上传播 DOM 层次结构,因此父 div 不会看到它,它的处理程序也不会触发。
如果我们立即停止传播,那么只会有 1 个警报。即使有三个事件处理程序附加到内部子 div,也只会执行 1 个,并且任何进一步的传播都会立即终止,即使在同一个元素内也是如此。
【讨论】:
stopPropagation() 变体也将停止向下传播 DOM 层次结构。不只是起来。请check my answer了解捕获阶段的详细信息。
令人惊讶的是,所有其他答案只说了一半或者实际上是错误的!
e.stopImmediatePropagation() 停止为此事件调用任何进一步的处理程序,没有例外e.stopPropagation() 类似,但仍会在 此元素 上调用 此阶段 的所有处理程序(如果尚未调用)什么阶段?
例如一个点击事件总是首先沿着 DOM 一路向下(称为“捕获阶段”),最后到达事件的起源(“目标阶段”),然后再次冒泡(“冒泡阶段”)。使用addEventListener(),您可以分别为捕获和冒泡阶段注册多个处理程序。 (目标阶段在目标上调用这两种类型的处理程序而不区分。)
这就是其他答案不正确的地方:
fiddle 和 mozilla.org event phase 的演示说明。
【讨论】:
event.stopPropagation 将阻止父元素上的处理程序运行。
调用event.stopImmediatePropagation 也会阻止同一元素上的其他处理程序运行。
【讨论】:
来自jQuery API:
除了保留任何额外的 元素上的处理程序 执行后,此方法也会停止 通过隐式调用冒泡 事件.stopPropagation()。简单来说 防止事件冒泡到 祖先元素,但允许其他元素 事件处理程序在同一个上执行 元素,我们可以使用 event.stopPropagation() 代替。
使用 event.isImmediatePropagationStopped() 知道这种方法是否曾经 调用(在那个事件对象上)。
简而言之:event.stopPropagation() 允许执行同一元素上的其他处理程序,而 event.stopImmediatePropagation() 阻止 每个 事件运行。
【讨论】:
event.stopImmediatePropagation 的原生 javascript 版本不会停止冒泡吧?
stopImmediatePropagation停止事件传播期间,它们都应该防止冒泡,你也可以改变模式为 capture,这将首先触发最外层的元素,然后才 down 到子 (冒泡是默认值,并且在相反的方向上工作)我>
我来晚了,但也许我可以用一个具体的例子说:
假设你有一个<table>,有<tr>,然后是<td>。现在,假设您为<td> 元素设置了3 个事件处理程序,那么如果您在为<td> 设置的第一个事件处理程序中执行event.stopPropagation(),那么<td> 的所有事件处理程序仍将运行,但该事件不会传播到<tr> 或<table>(也不会上升到<body>、<html>、document 和window)。
但是,现在,如果您在第一个事件处理程序中使用 event.stopImmediatePropagation(),那么 <td> 的其他两个事件处理程序将不会运行,并且不会传播到 @987654336 @、<table>(不会上升到 <body>、<html>、document 和 window)。
请注意,它不仅适用于<td>。对于其他元素,将遵循相同的原则。
【讨论】:
1)event.stopPropagation():
=>它仅用于停止其相应父处理程序的执行。
2) event.stopImmediatePropagation():
=> 它用于停止执行其相应的父处理程序以及附加到自身的处理程序或函数,但当前处理程序除外。
=> 它还会停止所有附加到整个 DOM 的当前元素的处理程序。
示例如下:Jsfiddle!
谢谢, -萨希尔
【讨论】:
这里有一个演示来说明区别:
document.querySelectorAll("button")[0].addEventListener('click', e=>{
e.stopPropagation();
alert(1);
});
document.querySelectorAll("button")[1].addEventListener('click', e=>{
e.stopImmediatePropagation();
alert(1);
});
document.querySelectorAll("button")[0].addEventListener('click', e=>{
alert(2);
});
document.querySelectorAll("button")[1].addEventListener('click', e=>{
alert(2);
});
<div onclick="alert(3)">
<button>1...2</button>
<button>1</button>
</div>
请注意,您可以将多个事件处理程序附加到元素上的事件。
【讨论】:
div 是被点击的button 的父级,stopPropagation() 确保3 永远不会被提醒,而stopImmediatePropagation() 确保甚至在button 本身上注册的其他事件侦听器(即2)都不会被执行。
event.stopPropagation() 允许执行同一元素上的其他处理程序,而 event.stopImmediatePropagation() 阻止每个事件运行。例如,请参见下面的 jQuery 代码块。
$("p").click(function(event)
{ event.stopImmediatePropagation();
});
$("p").click(function(event)
{ // This function won't be executed
$(this).css("color", "#fff7e3");
});
如果在前面的例子中使用了 event.stopPropagation,那么改变 css 的 p 元素上的下一个点击事件将会触发,但是如果是 event.stopImmediatePropagation() , 下一个 p 点击事件不会触发。
【讨论】:
在这里,我为 stopPropagation 与 stopImmediatePropagation 添加了我的 JSfiddle 示例。 JSFIDDLE
let stopProp = document.getElementById('stopPropagation');
let stopImmediate = document.getElementById('stopImmediatebtn');
let defaultbtn = document.getElementById("defalut-btn");
stopProp.addEventListener("click", function(event){
event.stopPropagation();
console.log('stopPropagation..')
})
stopProp.addEventListener("click", function(event){
console.log('AnotherClick')
})
stopImmediate.addEventListener("click", function(event){
event.stopImmediatePropagation();
console.log('stopimmediate')
})
stopImmediate.addEventListener("click", function(event){
console.log('ImmediateStop Another event wont work')
})
defaultbtn.addEventListener("click", function(event){
alert("Default Clik");
})
defaultbtn.addEventListener("click", function(event){
console.log("Second event defined will also work same time...")
})
div{
margin: 10px;
}
<p>
The simple example for event.stopPropagation and stopImmediatePropagation?
Please open console to view the results and click both button.
</p>
<div >
<button id="stopPropagation">
stopPropagation-Button
</button>
</div>
<div id="grand-div">
<div class="new" id="parent-div">
<button id="stopImmediatebtn">
StopImmediate
</button>
</div>
</div>
<div>
<button id="defalut-btn">
Normat Button
</button>
</div>
【讨论】: