摘要
很多同學對阻止事件冒泡和阻止事件默認行為容易混淆,項目中因為一些原因也需要阻止瀏覽器的一些默認行為,這里就簡單總結一下。
阻止事件冒泡
什么是事件冒泡這里就不再贅述了,網上的文章一大把,這里就簡述一下如何阻止事件冒泡,阻止事件冒泡在使用瀏覽器原生API的情況下,是需要分情況考慮的,畢竟有個個性的瀏覽器IE,這里分為IE實現和W3C標准實現。
在W3C標准實現中,我們阻止事件冒泡可以很容易使用標准API
基本語法:
event.stopPropagation();
IE實現下(這里主要指IE低版本IE9以下版本,因為IE9也實現了W3C標准)
基本語法:
event.cancelBubble = bool;
當然IE標准並不是只有IE支持,其實很多瀏覽器都實現了cancelBubble支持,但是后來雖然瀏覽器沒有取消對cancelBubble屬性的支持,設置了之后也會無效,所以建議的兼容語法是:
function eventCallback(e){
e = e||window.event;
if(e.stopPropagation){ //通過瀏覽器能力進行兼容性檢測
e.stopPropagation();
}else if(e.cancelBubble){
e.cancelBubble = true;
}
}
當然說到阻止事件冒泡這個問題,也要簡單提一下 event.stopPropagation 和event.stopImmediatePropagation的異同點:
- 相同點是兩者都能阻止標准事件注冊方式注冊的事件 (addEventListener,IE是attachEvent)向父級節點繼續冒泡
- 不同點從名字上可以看出,Immediate立即的意思,event.stopImmediatePropagation 不止能阻止往父級節點冒泡,還能阻止當前節點其它事件的繼續執行(比如往一個元素上注冊了多個事件,那么在第一個事件執行的時候,通過調用event.stopImmediatePropagation,會阻止其它事件的執行)
上面代碼需要注意的一點是,IE下e不存在,從window中獲取,簡單做了兼容處理。可以嘗試使用return false
阻止瀏覽器默認行為
在開始之前,首先需要了解什么是瀏覽器的默認行為,我這里簡單舉幾個例子:
- 點擊a標簽,如果設置了href會執行跳轉
- 點擊輸入框,輸入框會獲取焦點
- 點擊右鍵,會彈出瀏覽器右鍵菜單
- 點擊submit,會提交其所在表單
- 點擊checkbox 會選中或者反選
還有其他的很多,這里就不一一列舉了
同樣的對於阻止瀏覽器默認行為的實現也分為W3C標准實現和IE實現(這里也只是指IE9以下的實現)
在W3C標准實現中,其基本語法如下:
event.preventDefault();
在IE實現中,其基本語法如下:
window.event.returnValue = false;
所以其兼容版本偽代碼如下
function eventCallback(e){
e = e || window.event;
if(e.preventDefault){
e.preventDefault()
}else {
e.returnValue = false;
}
}
這里簡單那checkbox做一個小的demo:
<!DOCTYPE>
<html>
<head>
<title>preventDefault Demo</title>
</head>
<body>
<h1>Please click on the checkbox</h1>
<form>
<label for="chk_just_for_test">Checkbox:</label>
<input type="checkbox" id="chk_just_for_test"/>
</form>
<script>
let chk = document.querySelector('#chk_just_for_test');
chk.addEventListener('click',e=>{
console.log('sorry ,do not let you check this checkbox');
e.preventDefault(); // 這里不考慮IE低版本兼容性問題
})
</script>
</body>
</html>
有興趣的其它場景都可以寫個小demo 玩玩。
同樣W3C標准實現中,我們可以通過event.defaultPrevented 來確定event.preventDefault方法是否被調用,基本模式如下:
if (e.defaultPrevented) {
/* the default was prevented */
}
當然不是所有的事件都可以被cancel,瀏覽器也提供了cancelable屬性來判斷事件是否可以被取消,如果cancelable為false,那么便無法阻止瀏覽器的默認行為,如果在一個不可撤銷的事件上調用preventDefault,會拋出錯誤,所以建議在調用之前判斷事件是否可被取消.
下面是一個來自於mdn的例子,有興趣的可以直接看原文
https://developer.mozilla.org/en-US/docs/Web/API/Event/cancelable
瀏覽器廠商提議滾輪事件只有第一次可被取消
function preventScrollWheel(event) {
if (typeof event.cancelable !== 'boolean' || event.cancelable) {
// The event can be canceled, so we do so.
event.preventDefault();
} else {
// The event cannot be canceled, so it is not safe
// to call preventDefault() on it.
console.warn(`The following event couldn't be canceled:`);
console.dir(event);
}
}
document.addEventListener('wheel', preventCancelableEvents);
總結
阻止默認冒泡和阻止瀏覽器默認行為需要關注的是兼容性問題,其它內容大家只需要關注mdn,已經很詳細的列出了兼容問題,對前端&node有興趣的歡迎微信交流,如果你能看到彈框彈出微信二維碼的話😁。
附錄
每個API的瀏覽器兼容情況如下:
event.stopPropagation
event.stopImmediatePropagation
window.event.returnValue
event.preventDefault
event.cancelable
event.cancelBubble