event.stopPropagation 和 event.preventDefault 有什么区别?

What's the difference between event.stopPropagation and event.preventDefault?

提问人:Rudie 提问时间:5/11/2011 最后编辑:Arsen KhachaturyanRudie 更新时间:7/8/2023 访问量:631441

问:

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

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

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

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

JavaScript 事件 阻止默认 停止传播

评论


答:

1305赞 Raynos 5/11/2011 #1

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

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

例子

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>

使用 ,仅调用按钮单击处理程序,而 div 的单击处理程序永远不会触发。stopPropagation

如果您使用 ,则仅停止浏览器的默认操作,但 div 的单击处理程序仍会触发。preventDefault

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

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

要支持 IE8 及更低版本,请替换为和替换为stopPropagationcancelBubblepreventDefaultreturnValue

评论

14赞 freefaller 6/17/2014
值得注意的是(如果您不查看 MSDN 文档),则 和 are 都是属性(因此应该设置 ),并且 that 和 是方法(因此应该调用cancelBubblereturnValuecancelBubble = true;preventDefaultstopPropagationpreventDefault();)
4赞 Yuci 10/17/2018
@Raynos,请注意:event.stopPropagation() 不仅会阻止事件在事件链中冒泡,还会在捕获阶段停止事件传播 (developer.mozilla.org/en-US/docs/Web/API/Event/stopPropagation)
7赞 d512 6/22/2019
知道按钮单击的默认操作是什么会很有帮助,这样我就可以推断为什么它的工作方式与 .如果默认操作没有调用该方法,它是什么?stopDefault()stopPropagation()onclick
4赞 gaurav5430 10/5/2021
按钮的默认浏览器行为是什么?
1赞 Rafael Atías 5/31/2022
@gaurav5430,根据标准,默认行为取决于其类型和上下文:如果它是表单中的类型提交按钮,则默认行为将是提交表单。
23赞 VladL 3/25/2014 #2

这是这里的报价

事件.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 有效地阻止了父元素知道其子元素上的给定事件。

虽然一个简单的停止方法允许我们快速处理事件,但它是 重要的是要考虑你到底想做什么 鼓泡。我敢打赌,开发人员真正想要的只是preventDefault 90%的时间!错误地“停止”事件可能会导致 无数的麻烦;您的插件可能无法正常工作,并且您的 第三方插件可能会被砖砌。或者更糟糕的是 -- 你的代码 中断站点上的其他功能。

333赞 a5hk 5/30/2014 #3

术语

quirksmode.org

事件捕获

使用事件捕获时

               | |
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  \ /          |     |
|   -------------------------     |
|        Event CAPTURING          |
-----------------------------------

Element1 的事件处理程序首先触发,Element2 的事件处理程序最后触发。

事件冒泡

使用事件冒泡时

               / \
---------------| |-----------------
| element1     | |                |
|   -----------| |-----------     |
|   |element2  | |          |     |
|   -------------------------     |
|        Event BUBBLING           |
-----------------------------------

Element2 的事件处理程序首先触发,Element1 的事件处理程序最后触发。

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

                 | |  / \
-----------------| |--| |-----------------
| element1       | |  | |                |
|   -------------| |--| |-----------     |
|   |element2    \ /  | |          |     |
|   --------------------------------     |
|        W3C event model                 |
------------------------------------------

接口

w3.org,对于事件捕获

如果捕获希望阻止进一步处理 事件发生时,它可能会调用接口的方法。这将阻止事件的进一步调度, 尽管在同一层次结构中注册了其他 级别仍将收到该事件。调用事件的方法后,对该方法的进一步调用将没有 附加效果。如果不存在其他捕获器且尚未调用,则该事件将触发 适合目标本身。EventListenerstopPropagationEventEventListenersstopPropagationstopPropagationEventListeners

对于事件冒泡

任何事件处理程序都可以选择通过以下方式阻止进一步的事件传播 调用接口的方法。如果有人调用此方法,则在 电流将被触发,但冒泡将停止 水平。只需调用一次即可防止进一步 鼓泡。stopPropagationEventEventListenerEventListenersEventTargetstopPropagation

对于活动取消

取消是通过调用 的方法完成的。如果在 事件流的任何阶段,默认操作都将被取消。EventpreventDefaultEventListenerspreventDefault

例子

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

HTML格式:

<div id="a">
  <a id="b" href="http://www.google.com/">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();
}

阻止打开新选项卡。

评论

39赞 floribon 10/29/2014
感谢捕获和冒泡之间的更深层次的区别,而另一个答案仅解决 jQuery 问题。
5赞 Mike Clark 5/6/2015 #4

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

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

例如,如果 OR 内部附加了 click 方法的链接也附加了 click 方法,则它将阻止 or click 方法触发。DIVFORMDIVFORM

100赞 Keval Bhatt 5/27/2015 #5

返回 false;


return false;调用它时会做 3 件独立的事情:

  1. event.preventDefault()– 它停止浏览器的默认行为。
  2. event.stopPropagation()– 它阻止事件传播(或“冒泡”)DOM 。
  3. 停止回调执行,并在调用时立即返回。

请注意,此行为不同于普通(非 jQuery)事件处理程序,在普通(非 jQuery)事件处理程序中,值得注意的是,它不会阻止事件冒泡。return false

preventDefault();


preventDefault();做一件事:它停止浏览器的默认行为。

何时使用它们?


我们知道它们的作用,但何时使用它们?简单地说,这取决于你想完成什么。如果您想“只是”阻止默认浏览器行为,请使用。使用 return false;当您想要阻止默认浏览器行为并阻止事件传播 DOM 时。在大多数情况下,您会使用 return false;你真正想要的是.preventDefault();preventDefault()

例子:


让我们试着用例子来理解:

我们将看到纯 JAVASCRIPT 示例

示例 1:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

运行上面的代码,你会看到超链接“点击这里访问 stackoverflow.com'现在,如果您先单击该链接,您将获得 javascript 警报链接点击 接下来,您将获得 javascript 警报 div 单击,您将立即被重定向到 stackoverflow.com。

示例 2:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

运行上面的代码,你会看到超链接“点击这里访问 stackoverflow.com'现在,如果您先单击该链接,您将获得 javascript 警报链接点击 接下来,您将获得 javascript alert div 单击“下一步”,您将看到超链接“单击此处以 访问 stackoverflow.com“替换为文本”已阻止点击事件” 并且您不会被重定向到 stackoverflow.com。这是由于我们用来防止默认点击> event.preventDefault() 方法 要触发的操作。

示例 3:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('div Clicked');
  }
</script>

这一次,如果你点击链接,函数executeParent()不会 被调用,你不会得到javascript警报div这次点击。这是由于我们阻止了传播到 使用 event.stopPropagation() 方法的父 div。接下来,您将看到 超链接“按此浏览 stackoverflow.com”替换为文字 “点击事件将被执行”,您将立即被执行 已重定向至“stackoverflow.com”诊断树。这是因为我们没有阻止 这次触发的默认单击操作使用 event.preventDefault() 方法。

示例 4:

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.preventDefault();
    event.stopPropagation();
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

如果单击链接,函数 executeParent() 将不会 调用,您将不会收到 JavaScript 警报。这是由于我们 使用 event.stopPropagation() 方法。接下来,您将看到超链接“单击” 此处访问 stackoverflow.com“替换为文本”点击事件” 阻止“,您将不会被重定向到 stackoverflow.com。这 是因为我们阻止了默认的点击操作触发 这次使用 event.preventDefault() 方法。

示例 5:

对于返回 false,我有三个示例,它们似乎都在做完全相同的事情(只是返回 false),但实际上 结果大不相同。以下是每个 以上。

例:

  1. 从内联事件处理程序返回 false 会阻止浏览器导航到链接地址,但不会阻止事件通过 DOM 传播。
  2. 从 jQuery 事件处理程序返回 false 会阻止浏览器导航到链接地址,并阻止事件通过 DOM 传播。
  3. 从常规 DOM 事件处理程序返回 false 绝对不会执行任何操作。

将看到所有三个示例。

  1. 内联返回 false。

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='return false'>Click here to visit stackoverflow.com</a>
</div>
<script>
  var link = document.querySelector('a');

  link.addEventListener('click', function() {
    event.currentTarget.innerHTML = 'Click event prevented using inline html'
    alert('Link Clicked');
  });


  function executeParent() {
    alert('Div Clicked');
  }
</script>

  1. 从 jQuery 事件处理程序返回 false

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <a href='https://stackoverflow.com'>Click here to visit stackoverflow.com</a>
</div>
<script>
  $('a').click(function(event) {
    alert('Link Clicked');
    $('a').text('Click event prevented using return FALSE');
    $('a').contents().unwrap();
    return false;
  });
  $('div').click(function(event) {
    alert('Div clicked');
  });
</script>

  1. 从常规 DOM 事件处理程序返回 false。

<div onclick='executeParent()'>
  <a href='https://stackoverflow.com' onclick='executeChild()'>Click here to visit stackoverflow.com</a>
</div>
<script>
  function executeChild() {
    event.currentTarget.innerHTML = 'Click event prevented'
    alert('Link Clicked');
    return false
  }

  function executeParent() {
    alert('Div Clicked');
  }
</script>

希望这些例子是清楚的。尝试在 html 文件中执行所有这些示例,看看它们是如何工作的。

评论

0赞 Don Hatch 6/23/2023
“请注意,这种行为与普通的(非jQuery)事件处理程序不同,”在这一点上,这是一件令人惊讶和令人困惑的事情,因为在此之前的答案中的材料似乎根本没有谈论jQuery。
-4赞 Manish Singh 9/10/2017 #6

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

5赞 Nayas Subramanian 8/8/2018 #7

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');
});

结果将是

“元素已点击”

“容器已点击”

现在事件。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/

21赞 Junaid 12/24/2020 #8

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

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

返回 false;
通常出现在jQuery代码中,它可以防止浏览器的默认行为,防止事件冒泡 DOM,并立即从任何回调返回。

看看这个非常好和简单的 4 分钟阅读,上面的文章是从哪里拍摄的。

2赞 Eyosias Negash 3/23/2023 #9

和 都是 JavaScript 中事件对象上可用的方法,但它们在处理事件时有不同的用途。以下是它们差异的简要说明:event.stopPropagation()event.preventDefault()

  1. event.stopPropagation():此方法用于阻止事件在 DOM 层次结构中向上或向下传播(冒泡)。JavaScript 中的事件可以从目标元素冒泡到其祖先,也可以在它们沿着 DOM 层次结构向下时被捕获。使用 时,它会阻止事件到达父元素或祖先元素上的任何其他事件侦听器。但是,它不会阻止与事件关联的默认操作。event.stopPropagation()

示例用例:在可折叠菜单中的按钮上有一个单击事件侦听器。body 元素上还有另一个单击事件侦听器,当您单击菜单外部时,该侦听器会折叠菜单。通过使用按钮单击事件,可以防止事件到达正文单击事件侦听器,从而阻止菜单在单击按钮时折叠。event.stopPropagation()

  1. event.preventDefault():此方法用于防止浏览器与事件关联的默认行为。它不会影响事件本身的冒泡或捕获。调用此方法会通知浏览器要显式处理事件并重写其默认操作。

示例用例:您有一个带有提交按钮的表单,并且您希望在提交表单之前通过 JavaScript 验证表单。在提交事件侦听器中,可用于阻止将表单提交到服务器,直到执行验证逻辑并且表单通过验证。event.preventDefault()

总之,用于停止事件传播,而用于防止与事件关联的默认行为。它们可以单独使用,也可以一起使用,具体取决于您的特定事件处理要求。event.stopPropagation()event.preventDefault()