event.stopPropagation()event.stopImmediatePropagation()有什么区别?

#1 楼

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> 





请注意,事件绑定的顺序在这里很重要!




 $("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> 




评论


您强调“父母”,但实际上,如果在捕获阶段被调用,它们也都会停止输入孩子!有关详细信息,请参见我的答案。

– Robert Siemer
20 Mar 26 '20在7:07

#2 楼

一个小例子来说明这两种传播停止是如何工作的。




 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">&nbsp;</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层次结构。不只是上升。请检查我的答案以获取有关捕获阶段的详细信息。

– Robert Siemer
20 Mar 26 '20在7:10

#3 楼

在jQuery API中:


除了不执行元素上的任何其他
处理程序
,该方法还通过以下方法阻止
冒泡隐式调用
event.stopPropagation()。为了简单地
防止事件冒泡到
祖先元素,但允许其他
事件处理程序在同一
元素上执行,我们可以使用
event.stopPropagation()相反。

使用
event.isImmediatePropagationStopped()
知道是否曾经在该事件对象上调用过此方法。

event.stopPropagation()允许执行同一元素上的其他处理程序,而event.stopImmediatePropagation()则阻止运行每个事件。

评论


可以肯定的是,event.stopImmediatePropagation的本机javascript版本不会停止冒泡,对吗?

–亚历山大·德克(Alexander Derck)
16-10-11在21:12

确实如此,冒泡是指事件传播到父元素时,stopImmediatePropagation会阻止事件传播期间,这两者都应防止冒泡,这毫无用处,您还可以更改捕获模式,这将首先触发最外层元素然后才转到子级(默认为冒泡,并且朝相反的方向工作)

–JonnySerra
17年11月9日在20:56

至少可以说是不准确的。停止在捕获阶段将不允许在我的答案中说明的同一元素上执行气泡处理程序。

– Robert Siemer
20 Mar 26 '20在7:14

#4 楼

event.stopPropagation将阻止运行父元素上的处理程序。
调用event.stopImmediatePropagation也将阻止运行同一元素上的其他处理程序。

评论


值得一提的是,事件处理程序按照它们附加到元素的顺序执行。

–费利克斯·克林(Felix Kling)
2011年3月14日下午14:15

#5 楼

我来晚了,但是也许我可以举一个具体的例子:

说,如果您有一个<table><tr><td>。现在,假设您为<td>元素设置了3个事件处理程序,然后,如果在为event.stopPropagation()设置的第一个事件处理程序中执行<td>,则<td>的所有事件处理程序仍将运行,但事件不会传播到<tr><table>(不会增加到<body><html>documentwindow)。

现在,如果您在第一个事件处理程序中使用event.stopImmediatePropagation(),则另外两个事件处理程序<td>不会运行,并且不会传播到<tr><table>(也不会传播到<body><html>documentwindow)。

请注意,这不仅仅是为<td>。对于其他元素,它将遵循相同的原理。

#6 楼

令人惊讶的是,所有其他答案都只说了一半真话或实际上是错的!


e.stopImmediatePropagation()停止为此事件调用任何进一步的处理程序,没有例外

e.stopPropagation()相似,但如果尚未调用此元素,则仍会为此元素调用此阶段的所有处理程序

哪个阶段?
例如点击事件始终会一直沿DOM一直下去(称为“捕获阶段”),最后到达事件的起点(“目标阶段”),然后再次冒泡(“泡沫阶段”)。使用addEventListener(),您可以为捕获和气泡阶段分别注册多个处理程序。 (目标阶段没有区别地在目标上调用这两种类型的处理程序。)这是其他答案不正确的地方:

quote:“ event.stopPropagation()允许其他处理程序在更正:如果在捕获阶段中停止,则气泡阶段处理程序将永远无法到达,也将在同一元素上跳过它们。



引用:“ event.stopPropagation()[...]仅用于停止执行其相应的父处理程序”。

更正:如果在捕获阶段停止了传播,则处理程序在任何子对象上,包括目标对象上,都不会被调用,不仅是父对象
...而且:如果在气泡阶段停止传播,则已经调用了所有捕获阶段处理程序,包括在父对象上的捕获程序



演示中的小提琴和mozilla.org事件阶段说明。

#7 楼

1)event.stopPropagation():
=>仅用于停止执行其相应的父处理程序。

2)event.stopImmediatePropagation():
=>用于停止其相应的父处理程序的执行处理程序以及除当前处理程序之外附加到其自身的处理程序或函数。
=>它还停止附加到整个DOM当前元素的所有处理程序。

这里是示例:Jsfiddle!

,谢谢,
-Sahil

#8 楼

这是一个演示差异的演示:



 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是被单击的按钮的父级,因此stopPropagation()确保3永远不会发出警报,而stopImmediatePropagation()确保甚至没有其他事件侦听器在按钮本身上注册,即2 ,被执行。

–安德鲁(Andrew)
20-10-2在17:43

#9 楼

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,则将更改p元素上的下一个click事件,该事件将更改css ,但万一event.stopImmediatePropagation(),则不会触发下一个p单击事件。

#10 楼

在这里,我为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>