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

他们似乎也在做同样的事情……是一个现代人还是一个老人? 还是他们支持不同的浏览器?

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

那为什么呢? 我应该继续检查吗? 或者实际上有区别?

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

stopPropagation停止事件冒泡事件链。

preventDefault防止浏览器在该事件中进行的默认操作。

假设你有

 <div id="foo"> <button id="but" /> </div> $("#foo").click(function() { // mouse click on div }); $("#but").click(function(ev) { // mouse click on button ev.stopPropagation(); }); 

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

从quirksmode.org

事件捕获

当你使用事件捕获

                |  |
 --------------- |  | -----------------
 |  element1 |  |  |
 |  ----------- |  | ----------- |
 |  | element2 \ / |  |
 |  ------------------------- |
 | 事件捕获|
 -----------------------------------

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

事件冒泡

当你使用事件冒泡

                / \
 --------------- |  | -----------------
 |  element1 |  |  |
 |  ----------- |  | ----------- |
 |  | element2 |  |  |  |
 |  ------------------------- |
 | 事件BUBBLING |
 -----------------------------------

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

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

                  |  |  / \
 ----------------- |  |  -  |  | -----------------
 |  element1 |  |  |  |  |
 |  ------------- |  |  -  |  | ----------- |
 |  | element2 \ / |  |  |  |
 |  -------------------------------- |
 |  W3C事件模型|
 ------------------------------------------

https://www.w3.org/TR/DOM-Level-2-Events/events.html

如果捕获的EventListener希望阻止事件的进一步处理发生,则可以调用Event接口的stopPropagation方法。 这将阻止事件的进一步分派,尽pipe在相同层级上注册的附加EventListener仍将接收事件。 一旦事件的stopPropagation方法被调用,进一步调用该方法就没有其他的作用。 如果不存在其他捕获器,并且尚未调用stopPropagation,则该事件会在目标上触发相应的EventListener。

而为了冒泡:

任何事件处理程序都可以通过调用Event接口的stopPropagation方法来阻止进一步的事件传播。 如果任何EventListener调用此方法,则将触发当前EventTarget上的所有其他EventListener,但冒泡将在该级别停止。 只有一个呼叫停止传播是需要的,以防止进一步冒泡。

例如

HTML

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

JavaScript的

 var el = document.getElementById("c"); function captureOnClickA(e){ el.innerHTML += "DIV event capture<br>"; } function captureOnClickB(e){ el.innerHTML += "A event capture<br>"; } function bubblingOnClickA(e){ el.innerHTML += "DIV event bubbling<br>"; } function bubblingOnClickB(e){ el.innerHTML += "A event bubbling<br>"; } document.getElementById("a").addEventListener("click",captureOnClickA, true); document.getElementById("b").addEventListener("click",captureOnClickB, true); document.getElementById("a").addEventListener("click",bubblingOnClickA, false); document.getElementById("b").addEventListener("click",bubblingOnClickB, false); 

Demo ,在这个例子中,执行四个事件监听器,并在浏览器中打开一个新的标签。 输出是:

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

将第一个function更改为:

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

将导致这个输出:

 DIV event capture 

这意味着事件的向下传播停止并且其向上传播。 演示 。 但是它不会阻止标签的打开。

stopPropagation()添加到

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

演示或

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

演示 ,将导致相同的输出,因为他们在当前EventTarget:

 DIV event capture A event capture A event bubbling 

在这两种情况下,这个事件阻止了向父母冒泡。 这两个也不会阻止选项卡打开。 为了防止打开标签,我们需要使用preventDefault()来防止默认的浏览器操作:

 function captureOnClickA(e){ el.innerHTML += "DIV event capture<br>"; e.stopPropagation(); e.preventDefault(); } 

现在该选项卡将不会打开,只有一个事件侦听器将被执行。 演示 。

返回false;


return false; 当你调用它时是否有三个独立的东西:

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

请注意,这种行为不同于普通(非jQuery)事件处理程序,其中,特别是, return false不会阻止事件冒泡。

的preventDefault();


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

何时使用它们?


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

例子:


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

我们将看到纯JAVASCRIPT的例子

例1:

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

这是从这里引用

Event.preventDefault

preventDefault方法可以防止事件执行其默认function。 例如,您可以使用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!'); }; 

虽然该元素的默认function是砖,事件继续冒泡的DOM。

Event.stopPropagation

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

 //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%的时间! 错误地“停止”一个事件可能会导致你无数的麻烦。 您的插件可能无法正常工作,您的第三方插件可能会被堵塞。 或者更糟糕的是,您的代码会破坏网站上的其他function。

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

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

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

例如,如果附加点击方法的DIVFORM内部附带有点击方法的链接,则将阻止DIVFORM点击方法触发。