JavaScript 事件機制
事件流是一個事件沿著特定數據結構傳播的過程。冒泡和捕獲是事件流在DOM中兩種不同的傳播方法。
事件流有三個階段:
- 事件捕獲階段
- 處於目標階段
- 事件冒泡階段
什麽是捕獲和冒泡
假設有節點如下:
<div id="div1">
<div id="div2"></div>
</div>
<script>
let div1 = document.getElementById(‘div1‘);
let div2 = document.getElementById(‘div2‘);
div1.onClick = function(){
alert(‘1‘)
}
div2.onClick = function(){
alert(‘2‘);
}
</script>
當點擊 div2時,會彈出兩個彈出框。在 ie8/9/10、chrome瀏覽器,會先彈出"2"再彈出“1”,這就是事件冒泡:事件從最底層的節點向上冒泡傳播。事件捕獲則跟事件冒泡相反。
W3C的標準是先捕獲再冒泡, addEventListener
的第三個參數決定把事件註冊在捕獲(true)還是冒泡(false)
事件綁定
在各種瀏覽器中綁定事件有不同的寫法。
傳統的事件綁定:在元素上使用 onClick綁定。
它可以適應不同的瀏覽器,但是只能在事件冒泡中運行(捕獲不行),一次只能綁定一個。
var ele = document.getElementById(‘xDiv‘);
ele.onClick = function(e){
console.log(‘指向當前的this‘,this);
console.log(e.currentTarget);
}
w3c事件綁定:使用addEventListener()函數
這種綁定支持冒泡和 捕捉,同時可以對一個元素進行多次綁定,按書寫先後順序執行。
var ele = document.getElement(‘xDiv‘);
// 最後一個參數表示事件的處理階段,true是捕獲,false是冒泡
ele.addEventListener(‘click‘,(e)=>{
console.log(e);
},true);
但是IE9以下不支持 addEventListener
函數,IE瀏覽器要使用 attachEvent
函數代替。
IE的事件綁定:attachEvent
函數支持全系列IE,但是其他瀏覽器不支持。
var ele = document.getElementById(‘xDiv‘);
ele.attachEvent(‘onclick‘,()=>{
console.log(‘指向全局的this‘,this);
});
attachEvent
支持事件捕捉階段,不支持冒泡階段。
另外需要註意的是 attachEvent
的執行順序是從後往前。
兼容寫法
如果我們要兼容多個瀏覽器的事件綁定,則可以這樣寫
if(window.addEventListener){
//chrom firefor ...
object.addEventListener(‘click‘,function(){
},false);
}
else if(window.attachEvent){
//IE
object.attachEvent(‘onclick‘,function(){})
}
else{
object.onclick = function(){}
}
事件流阻止
在一些情況下需要阻止事件流的傳播,阻止默認動作的發生。
event.preventDefault()
:取消事件對象的默認動作以及繼續傳播。
event.stopPropagation()
/ event.cancelBubble = true
:阻止事件冒泡。
事件的阻止在不同瀏覽器有不同處理
- 在IE下使用
event.returnValue= false
, - 在非IE下則使用
event.preventDefault()
進行阻止。
preventDefault
與stopPropagation
的區別:
-
preventDefault
告訴瀏覽器不用執行與事件相關聯的默認動作(如表單提交) -
stopPropagation
是停止事件繼續冒泡,但是對IE9以下的瀏覽器無效
事件委托
在js中性能優化的其中一個主要思想是減少dom操作。
假設有100個li,每個li有相同的點擊事件。如果為每個Li都添加事件,則會造成dom訪問次數過多,引起瀏覽器重繪與重排的次數過多,性能則會降低。
使用事件委托則可以解決這樣的問題。
原理
實現事件委托是利用了事件的冒泡原理實現的。當我們為最外層的節點添加點擊事件,那麽裏面的ul、li、a的點擊事件都會冒泡到最外層節點上,委托它代為執行事件。
實現
<ul id="ul">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
window.onload = function(){
var ulEle = document.getElementById(‘ul‘);
ul.onclick = function(ev){
//兼容IE
ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == ‘li‘){
alert( target.innerHTML);
}
}
}
作者:Guanmac
鏈接:https://www.jianshu.com/p/916230ad9229
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並註明出處。
JavaScript 事件機制