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;
当你调用它时是否有三个独立的东西:
-
event.preventDefault()
– 它停止浏览器的默认行为。 -
event.stopPropagation()
– 防止事件传播(或“冒泡”)DOM。 - 停止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树,阻止任何父处理程序被通知事件。
例如,如果附加点击方法的DIV
或FORM
内部附带有点击方法的链接,则将阻止DIV
或FORM
点击方法触发。