1010

他们似乎在做同样的事情……
一个现代的,一个古老的?或者它们是否被不同的浏览器支持?

当我自己处理事件(没有框架)时,我总是检查两者并执行两者(如果存在)。(我也是return false,但我感觉不适用于附带的事件node.addEventListener)。

那为什么两者兼而有之?我应该继续检查两者吗?还是真的有区别?

(我知道,很多问题,但它们都是一样的=))

4

8 回答 8

1197

stopPropagation防止当前事件在捕获和冒泡阶段进一步传播。

preventDefault阻止浏览器对该事件执行的默认操作。

例子

防止默认

$("#but").click(function (event) {
  event.preventDefault()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

停止传播

$("#but").click(function (event) {
  event.stopPropagation()
})
$("#foo").click(function () {
  alert("parent click event fired!")
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

使用stopPropagation时,只有button' 的点击处理程序被调用,而div' 的点击处理程序永远不会触发。

就像您使用 一样preventDefault,只有浏览器的默认操作会停止,但 div 的点击处理程序仍然会触发。

下面是一些来自 MDN 的关于 DOM 事件属性和方法的文档:

对于 IE9 和 FF,您可以只使用 preventDefault 和 stopPropagation。

支持 IE8 及更低版本替换stopPropagationcancelBubble和替换preventDefaultreturnValue

于 2011-05-11T11:46:34.027 回答
306

术语

来自quirksmode.org

事件捕获

当您使用事件捕获时

               | |
---------------| |-----------------
| 元素1 | | |
| ------------| |----------- |
| |元素2 \ / | |
| ------------------------------------- |
| 事件捕捉 |
----------------------------------

element1 的事件处理程序首先触发,element2 的事件处理程序最后触发。

事件冒泡

当您使用事件冒泡时

               / \
---------------| |-----------------
| 元素1 | | |
| ------------| |----------- |
| |元素2 | | | |
| ------------------------------------- |
| 事件冒泡 |
----------------------------------

element2 的事件处理程序首先触发,element1 的事件处理程序最后触发。

在 W3C 事件模型中发生的任何事件首先被捕获,直到它到达目标元素,然后再次冒泡

                 | | / \
-----------------| |--| |-----------------
| 元素1 | | | | |
| -------------| |--| |----------- |
| |元素2 \ / | | | |
| -------------------------------- |
| W3C 事件模型 |
------------------------------------------

界面

来自w3.org,用于事件捕获

如果捕获EventListener希望阻止事件的进一步处理发生,它可以调用接口的stopPropagation方法 Event。这将阻止事件的进一步分派,尽管EventListeners在同一层次结构级别注册的其他人仍将接收该事件。一旦调用了事件的stopPropagation 方法,对该方法的进一步调用就不会产生额外的影响。如果不存在额外的捕获器并且 stopPropagation未被调用,则该事件会EventListeners在目标本身上触发相应的捕获器。

对于事件冒泡

stopPropagation任何事件处理程序都可以选择通过调用接口的方法来阻止进一步的事件传播Event。如果有任何 EventListener调用此方法,则将触发EventListeners当前的所有附加内容,但在该级别将停止冒泡。EventTargetstopPropagation需要一次调用即可防止进一步冒泡。

对于事件取消

取消是通过调用Event'preventDefault 方法完成的。如果在事件流的任何阶段有一个或多个EventListeners调用,默认操作将被取消。preventDefault

例子

在以下示例中,单击 Web 浏览器中的超链接会触发事件流(执行事件侦听器)和事件目标的默认操作(打开新选项卡)。

HTML:

<div id="a">
  <a id="b" href="http://www.google.com/" target="_blank">Google</a>
</div>
<p id="c"></p>

JavaScript:

var el = document.getElementById("c");

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
}

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
}

function bubblingOnClick1(ev) {
    el.innerHTML += "DIV event bubbling<br>";
}

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
}

// The 3rd parameter useCapture makes the event listener capturing (false by default)
document.getElementById("a").addEventListener("click", capturingOnClick1, true);
document.getElementById("b").addEventListener("click", capturingOnClick2, true);
document.getElementById("a").addEventListener("click", bubblingOnClick1, false);
document.getElementById("b").addEventListener("click", bubblingOnClick2, false);

示例 1:它导致输出

DIV event capture
A event capture
A event bubbling
DIV event bubbling

示例 2:添加stopPropagation()到函数

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.stopPropagation();
}

结果输出

DIV event capture

事件侦听器阻止了事件的进一步向下和向上传播。但是,它并没有阻止默认操作(新标签打开)。

示例 3:添加stopPropagation()到函数

function capturingOnClick2(ev) {
    el.innerHTML += "A event capture<br>";
    ev.stopPropagation();
}

或功能

function bubblingOnClick2(ev) {
    el.innerHTML += "A event bubbling<br>";
    ev.stopPropagation();
}

结果输出

DIV event capture
A event capture
A event bubbling

这是因为两个事件侦听器都注册在同一个事件目标上。事件侦听器阻止了事件的进一步向上传播。但是,他们并没有阻止默认操作(新标签打开)。

示例 4:添加preventDefault()到任何函数,例如

function capturingOnClick1(ev) {
    el.innerHTML += "DIV event capture<br>";
    ev.preventDefault();
}

防止打开新标签。

于 2014-05-30T12:16:47.420 回答
86
于 2015-05-27T07:14:43.067 回答
20

这是这里的报价

Event.preventDefault

preventDefault 方法阻止事件执行其默认功能。例如,您可以在 A 元素上使用 preventDefault 来阻止单击该元素离开当前页面:

//clicking the link will *not* allow the user to leave the page 
myChildElement.onclick = function(e) { 
    e.preventDefault(); 
    console.log('brick me!'); 
};

//clicking the parent node will run the following console statement because event propagation occurs
logo.parentNode.onclick = function(e) { 
    console.log('you bricked my child!'); 
};

当元素的默认功能被阻塞时,该事件继续在 DOM 中冒泡。

Event.stopPropagation

第二种方法 stopPropagation 允许事件的默认功能发生但阻止事件传播:

//clicking the element will allow the default action to occur but propagation will be stopped...
myChildElement.onclick = function(e) { 
    e.stopPropagation();
    console.log('prop stop! no bubbles!'); 
};

//since propagation was stopped by the child element's onClick, this message will never be seen!
myChildElement.parentNode.onclick = function(e) { 
    console.log('you will never see this message!'); 
};

stopPropagation 有效地阻止父元素了解其子元素的给定事件。

虽然简单的停止方法可以让我们快速处理事件,但重要的是要考虑冒泡究竟想要发生什么。我敢打赌,开发人员真正想要的只是 90% 的时间防止默认设置!错误地“停止”一个事件可能会给你带来很多麻烦;您的插件可能无法正常工作,并且您的第三方插件可能会变砖。或者更糟糕的是——您的代码破坏了网站上的其他功能。

于 2014-03-25T14:55:59.863 回答
7

event.preventDefault()
阻止浏览器的默认行为(例如打开链接),但不会阻止事件冒泡 DOM。

event.stopPropagation()
防止事件冒泡 DOM,但不会停止浏览器的默认行为。

返回假;
通常在 jQuery 代码中看到,它防止浏览器默认行为,防止事件冒泡 DOM,并立即从任何回调中返回。

看看这个非常好的和简单的 4 分钟阅读,上面有上面的例子。

于 2020-12-24T11:43:17.123 回答
4

event.preventDefault();阻止元素的默认操作发生。

event.stopPropagation();防止事件在 DOM 树中冒泡,防止任何父处理程序收到事件通知。

例如,如果在 a 中附加了一个带有 click 方法的链接,DIV或者FORM还附加了一个 click 方法,它将阻止DIVor FORMclick 方法触发。

于 2015-05-06T11:32:02.290 回答
3

Event.preventDefault- 停止浏览器默认行为。现在是浏览器默认行为。假设你有一个锚标签,它有一个 href 属性,并且这个锚标签嵌套在一个有点击事件的 div 标签内。锚标签的默认行为是单击它应该导航的锚标签时,但 event.preventDefault 所做的是在这种情况下停止导航。但它永远不会停止事件的冒泡或事件的升级,即

<div class="container">
 <a href="#" class="element">Click Me!</a>
</div>

$('.container').on('click', function(e) {
 console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  console.log('element was clicked');
});

结果将是

“元素被点击”

“容器被点击”

现在 event.StopPropation 它停止事件冒泡或事件升级。现在有了上面的例子

$('.container').on('click', function(e) {
  console.log('container was clicked');
});

$('.element').on('click', function(e) {
  e.preventDefault(); // Now link won't go anywhere
  e.stopPropagation(); // Now the event won't bubble up
 console.log('element was clicked');
});

结果将是

“元素被点击”

有关更多信息,请参阅此链接 https://codeplanet.io/preventdefault-vs-stoppropagation-vs-stopimmediatepropagation/

于 2018-08-08T06:47:26.343 回答
-4

$("#but").click(function(event){
console.log("hello");
  event.preventDefault();
 });


$("#foo").click(function(){
 alert("parent click event fired !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo">
  <button id="but">button</button>
</div>

于 2017-09-10T03:57:12.077 回答