在複習事件這塊的時候,發現了一個問題,網上不少文章對事件阻止這塊解析的並不全面,而且有些文章也有錯誤之處,因而想本身總結一下,也方便本身的複習。html
在看本篇文章以前,須要瞭解事件的冒泡和捕獲,這裏簡單介紹下
事件冒泡: 即事件開始時由最具體的元素(文檔中嵌套層數最深的那個點)接收,而後逐級向上傳播到較爲不具體的節點(文檔),可理解爲:瀏覽器
由div->body->html->document
事件捕獲:不太具體的節點應該更早接收到事件,而最具體的節點應該最後接收到事件,可理解爲:dom
由document->html->body->div
DOM2級規定的事件流包括三個階段:事件捕獲階段、處於目標階段、事件冒泡階段函數
與此同時,咱們還須要瞭解dom事件綁定處理的幾種方式this
①、HTML事件處理(在dom元素中嵌入)code
<button onclick="fn()"></button>
缺點:
一、this指向window
二、HTML與JS緊密耦合,改動代碼麻煩
②、DOM0級事件處理(獲取dom元素直接綁定)htm
document.getElementById('btn').onclick = fn
優勢:
一、this指向dom元素
二、不存在瀏覽器兼容問題
③、DOM2級事件處理(事件監聽)對象
document.getElementById('btn').addEventListener('click',fn)
優勢: this指向dom元素
缺點: 一、 須要對IE8及如下進行兼容
document.getElementById('btn').attachEvent('click',fn)
因爲IE8及如下只支持事件冒泡,因此經過attachEvent都會被添加到冒泡階段
IE中的attachEvent中的this老是指向全局對象Window
event.stopPropagation()
做用: 終止事件在傳播過程的捕獲、目標處理或起泡階段進一步傳播兼容:在IE<9的瀏覽器上使用 event.cancelBubble = true事件
event.preventDefault()
做用: 取消事件的默認動做
備註:只有cancelable屬性爲true的事件,纔可使用preventDefault()
兼容:在IE瀏覽器中經過 e.returnValue = false
return false
return在函數中有三個做用:
一、用來返回一些值,固然也能夠不寫返回值
二、終止函數的執行,就是說在return以後的代碼都不會執行
三、在DOM0級事件中,能夠像event.preventDefault() 取消默認事件,可是在DOM2級則不行
event.stopImmediatePropagation()
做用: 阻止事件冒泡而且阻止相同事件的其餘偵聽器被調用。備註:阻止相同事件的其餘偵聽器被調用指的是: 若是有多個相同類型事件的事件監聽函數綁定到同一個元素,當該類型的事件觸發時,它們會按照被添加的順序執行。若是其中某個監聽函數執行了 event.stopImmediatePropagation() 方法,則當前元素剩下的監聽函數將不會被執行。ip
接下來咱們來驗證一下,建立一個html文件,寫入以下代碼
<html lang="en"> <head> <meta charset="UTF-8"> <title>阻止默認事件和冒泡</title> <style> div{width: 300px; height: 300px; background-color: pink;} </style> <script> // 接下來要寫的代碼 </script> </head> <body> </body> </html>
本次驗證所監聽的事件是
oncontextmenu
oncontextmenu 事件在元素中用戶右擊鼠標時觸發並打開上下文菜單
因爲一個個驗證比較麻煩,這裏把全部的代碼都寫出來
第一個是針對DOM0級事件的JS代碼
document.querySelector("div").oncontextmenu = function(event){ event.stopImmediatePropagation(); // 能夠阻止事件傳播 event.stopPropagation(); // 能夠阻止事件傳播 event.preventDefault(); // 能夠阻止默認事件 return false; // 能夠阻止默認事件 console.log("dom0-div"); }; document.oncontextmenu = function(event){ event.preventDefault(); // 能夠阻止默認事件 return false; // 能夠阻止默認事件 console.log("dom0-document"); };
第二個是針對DOM2級事件的JS代碼
document.querySelector("div").addEventListener('contextmenu', function(event){ event.stopImmediatePropagation(); // 能夠阻止事件傳播 event.stopPropagation(); // 能夠阻止事件傳播 event.preventDefault(); // 能夠阻止默認事件 // return false; // 不能阻止默認事件 console.log("dom2-div") }); document.addEventListener('contextmenu', function(event){ event.preventDefault(); // 能夠阻止默認事件 // return false; // 不能阻止默認事件 console.log("dom2-document") });
驗證是否能夠成功阻止事件傳播:
右擊div元素,控制檯查看是否有dom0-document 或者 dom2-document;
若是沒有,則阻止成功,若是有,則阻止失敗。
驗證是否能夠成功阻止默認事件:
右擊鼠標,看是否會出現菜單欄;
若是沒有,則阻止成功,若是有,則阻止失敗。
這裏重點提一下 stopImmediatePropagation(),
這個方法除了阻止事件冒泡還能夠阻止相同事件的其餘偵聽器被調用。
看如下例子:
const div = document.querySelector('div'); document.addEventListener("click", (event) => { console.log("document事件"); // event.stopImmediatePropagation()具備事件傳播的效果,因此這裏不會執行 }); div.addEventListener("click", (event) => { console.log("第1個事件"); }); div.addEventListener("click", (event) => { console.log("第2個事件"); event.stopImmediatePropagation(); }); div.addEventListener("click", (event) => { console.log("第3個事件"); // event.stopImmediatePropagation()具備阻止相同事件的其餘偵聽器被調用的效果,因此這裏不會執行 });