stopPropagation与stopImmediatePropagation

Arj*_*jun 285 javascript jquery

event.stopPropagation()和之间有什么区别event.stopImmediatePropagation()

Dav*_*ave 296

stopPropagation将防止任何被执行的处理程序stopImmediatePropagation将防止任何父处理程序,并且还任何其他处理程序从执行

jquery文档中的快速示例:

$("p").click(function(event) {
  event.stopImmediatePropagation();
});

$("p").click(function(event) {
  // This function won't be executed
  $(this).css("background-color", "#f00");
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>example</p>
Run Code Online (Sandbox Code Playgroud)

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

$("p").click(function(event) {
  // This function will now trigger
  $(this).css("background-color", "#f00");
});

$("p").click(function(event) {
  event.stopImmediatePropagation();
});
Run Code Online (Sandbox Code Playgroud)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>example</p>
Run Code Online (Sandbox Code Playgroud)

  • @Arjun:你正在使用`live`,它的工作方式不同.阅读文档:http://api.jquery.com/live/和http://api.jquery.com/event.stopImmediatePropagation/上的评论 (9认同)
  • 您强调“父级”,但实际上,如果在捕获阶段调用,两者也会停止进入子级![详细信息请参阅我的答案。](/sf/answers/4260362361/) (4认同)
  • _会做同样的事情,但也阻止其他处理程序执行_****其他处理程序?相同的处理程序类型?点击将停止点击.但它会停止 - 例如dblclick? (2认同)
  • 先生,在javascript中有event.StartImmediatePropogation()的函数吗? (2认同)
  • @AndrewFount是的,如果您完全控制代码:将相关处理程序移动到捕获阶段,该阶段在冒泡阶段之前,并允许您在向下的过程中中断调用链(而不是在向上的过程中)。 (2认同)

Anu*_*rag 57

一个小例子来演示这些传播停止是如何工作的.

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('---------------------');
});
Run Code Online (Sandbox Code Playgroud)
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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

绑定了三个事件处理程序.如果我们不停止任何传播,那么应该有四个警报 - 在子div上有三个,在父div上有一个.

如果我们阻止事件传播,那么将有3个警报(全部在内部子div上).由于事件不会传播到DOM层次结构中,因此父div不会看到它,并且它的处理程序不会触发.

如果我们立即停止传播,那么只会有1个警报.即使有三个事件处理程序附加到内部子div,也只执行1个,并且即使在同一个元素内也会立即杀死任何进一步的传播.

  • 最佳答案恕我直言。阅读了如此多的文字后,您的小提琴使其变得清晰而简单。除代码外,我无需阅读其他任何内容。谢谢! (2认同)

Rob*_*mer 37

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

  • e.stopImmediatePropagation() 停止为此事件调用任何进一步的处理程序,没有例外
  • e.stopPropagation()是相似的,但确实还呼吁所有的处理程序这一阶段这个元素如果不是已经叫

什么阶段?

例如,一个点击事件总是首先沿着 DOM 向下(称为“捕获阶段”),最后到达事件的起点(“目标阶段”),然后再次冒泡(“冒泡阶段”)。并且addEventListener()您可以独立地为捕获和冒泡阶段注册多个处理程序。(目标阶段在不区分的情况下调用目标上的两种类型的处理程序。)

这就是其他答案不正确的地方:

  • 引用:“event.stopPropagation() 允许执行同一元素上的其他处理程序”
    • 更正:如果在捕获阶段停止,将永远不会到达气泡阶段处理程序,也会在同一元素上跳过它们
  • 引用:“event.stopPropagation() [...] 仅用于停止其相应父处理程序的执行”
    • 更正:如果在捕获阶段停止传播则不会调用任何孩子的处理程序,包括目标,不仅是父母
    • ...并且:如果在冒泡阶段停止传播,则所有捕获阶段处理程序都已被调用,包括父级处理程序

一个小提琴和mozilla.org事件阶段与演示说明。

  • 这应该是公认的答案。 (7认同)
  • @Coder23不,不对。目标元素的处理程序列表只会被访问一次。所有处理程序都将被调用,忽略布尔值,否则决定是否在向下或向上的过程中调用它。即,较早注册的处理程序将被较早调用,即使该布尔值为 False 表示“冒泡阶段”。之后将调用显示 True(“捕获阶段”)的稍后注册的处理程序。 (2认同)

Aro*_*eel 27

来自jQuery API:

除了保持元素上的任何其他处理程序不被执行之外,此方法还通过隐式调用event.stopPropagation()来停止冒泡.要简单地阻止事件冒泡到祖先元素但允许其他事件处理程序在同一元素上执行,我们可以使用event.stopPropagation()代替.

使用event.isImmediatePropagationStopped()来了解是否曾调用此方法(在该事件对象上).

简而言之:event.stopPropagation()允许执行同一元素上的其他处理程序,同时event.stopImmediatePropagation()防止每个事件运行.


SLa*_*aks 23

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

  • 值得一提的是,事件处理程序按照它们附加到元素的顺序执行. (20认同)

nop*_*ole 16

我是后来者,但也许我可以用一个具体的例子说这个:

说,如果你有<table>,有<tr>,然后<td>.现在,假设你为<td>元素设置了3个事件处理程序,然后如果你event.stopPropagation()在你设置的第一个事件处理程序中执行<td>,那么所有事件处理程序<td>仍将运行,但事件不会传播到<tr><table>(并且不会上去达<body>,<html>,document,和window).

但是现在,如果你使用event.stopImmediatePropagation()你的第一个事件处理程序,那么,对于其他两个事件处理程序<td>将不会运行,并且不会传播到<tr>,<table>(并不会上去达<body>,<html>,document,和window).

请注意,它不只是为了<td>.对于其他元素,它将遵循相同的原则.


Sah*_*war 8

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

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

这是一个例子:Jsfiddle!

谢谢,-Sahil


Cho*_*ang 7

这是一个演示来说明差异:

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);
});
Run Code Online (Sandbox Code Playgroud)
<div onclick="alert(3)">
   <button>1...2</button>
   <button>1</button>
</div>
Run Code Online (Sandbox Code Playgroud)

请注意,您可以将多个事件处理程序附加到元素上的一个事件。