早期由於瀏覽器廠商對於瀏覽器市場的爭奪,各家瀏覽器廠商對同一功能的JavaScript的實現都不進相同,本節內容介紹JavaScript的DOM事件模型及事件處理程式的分類。 1、DOM事件模型。DOM事件模型分為兩種:事件冒泡和事件捕獲。事件冒泡最初是微軟提出的DOM事件流的模型,顧名思義,就是值 ...
早期由於瀏覽器廠商對於瀏覽器市場的爭奪,各家瀏覽器廠商對同一功能的JavaScript的實現都不進相同,本節內容介紹JavaScript的DOM事件模型及事件處理程式的分類。
1、DOM事件模型。DOM事件模型分為兩種:事件冒泡和事件捕獲。事件冒泡最初是微軟提出的DOM事件流的模型,顧名思義,就是值瀏覽器的事件流如同冒泡一樣,從最低處到最高處。最低處對應的是DOM中最具體的元素,最高處則是最外層元素,最外層元素一般就是document元素。
a、事件冒泡模型:
如下圖,當點擊最底層的span元素時,在冒泡模型中觸發的事件流為:span的click事件觸發---->父級元素div的click事件觸發---->頂層的document元素的click事件觸發。
b、事件捕獲模型:
如下圖,當點擊span元素時,在事件捕獲模型中觸發的事件流為:最頂層的document的click事件首先被觸發---->子容器div(同時也是span的父容器)的click事件被觸發
---->最底層的span元素的click事件觸發。
可見,事件冒泡和事件捕獲的事件觸發流程是完全相反的。
2、DOM事件處理程式的分類。DOM事件處理程式分為三種:HTML事件處理程式、DOM 0級事件處理程式、DOM 2級事件處理程式(註意:、沒有DOM1級事件處理程式)。
a、HTML事件處理程式:
指的是事件綁定直接寫在HTML上,如:
1 <input type="button' value="button" onclick="alert('button clicked!')" />
這裡button的click事件的綁定直接寫在HTML中,這種寫法即是HTML事件處理程式。由於這種寫法造成HTML和JavaScript的緊耦合,當需要調整JavaScript事件時,不得不調整HTML代碼(就算不修改JavaScript函數名,只修改函數的內部實現,仍然不推薦使用這種語法綁定事件,會增加不必要的維護成本)。
b、DOM 0級事件處理程式:
指的是通過給JavaScript對象的事件參數屬性賦值的模式,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.onclick = function(){ 5 alert("button clicked!"); 6 } 7 </script>
這裡通過直接給btnDOM對象的onclick屬性賦值的形式來綁定click事件就是DOM 0級事件處理程式,賦值可以使用匿名函數的形式,也可以使用具名函數的形式,如下:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.onclick clickHandle; 5 function clickHandle(){ 6 alert("something clicked!"); 7 } 8 </script>
如需註銷,只需將該屬性設置為null即可,如下:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.onclick clickHandle; 5 function clickHandle(){ 6 alert("something clicked!"); 7 } 8 btn.onclick = null; 9 </script>
註意:如果綁定使用的是匿名函數的形式,通過給事件屬性賦值null仍然可以註銷該事件。
c、DOM 2級事件處理程式:
指的是使用 addEventListener("eventName","eventHandle",false),其中eventName表示事件名稱、eventHandle表示事件處理函數,false表示是否啟用事件捕獲模式,預設為false。使用addEventListener函數來給DOM元素綁定事件處理程式,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.addEventListener("click",function(){ 5 alert("something clicked!"); 6 },false); 7 </script>
同樣,這裡既可以使用匿名函數的形式也可以使用具名函數的形式,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.addEventListener("click",clickHandle,false); 5 function clickHandle(){ 6 alert("something clicked!"); 7 } 8 </script>
註意:通過addEventListener綁定的事件只能通過removeEventListener來註銷,不能使用DOM 0級中的方式註銷事件處理程式,註銷事件如下:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.addEventListener("click",clickHandle,false); 5 function clickHandle(){ 6 alert("something clicked!"); 7 } 8 btn.removeEventListener("click",clickHandle); 9 </script>
如果綁定時使用的是匿名函數,則註銷操作比較麻煩,可以通過事件參數的callee屬性獲取當前正在執行的函數,但必須使用在事件綁定的函數內,如:
1 <script> 2 var dom=document.getElementById("content"); 3 var clickNum=0; 4 dom.addEventListener("click",function(e){ 5 clickNum++; 6 alert('你摸了我'+clickNum+'下了。最多摸2下哦'); 7 if(clickNum>=2){ 8 dom.removeEventListener(e.type,arguments.callee,false); 9 console.log(this); 10 } 11 }); 12 </script>
d、IE中DOM 2級事件處理程式的是通過attachevent來綁定的,語法與addEventListener完全一致。
e、DOM 0級和DOM 2級事件處理程式的主要區別:
DOM 2級事件處理程式可以給元素的事件綁定多個處理程式,如:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.addEventListener("click",clickHandle1,false); 5 btn.addEventListener("click",clickHandle2,false); 6 function clickHandle1(){ 7 alert("something clicked!"); 8 } 9 function clickHandle2(){ 10 alert("something clicked again!"); 11 } 12 </script>
此時,點擊btn時將會依次觸發clickHandle1、clickHandle2,註銷事件處理程式也需要針對每個事件處理程式使用removeEventListener。
DOM 0級事件處理程式如果以這種形式綁定事件,則後寫的方法會覆蓋掉之前的方法,即:
1 <input id="btn" type="button" value="button" /> 2 <script> 3 var btn = document.getElementById("btn"); 4 btn.onclick = clickHandle1(); 5 btn.onclick = clickHandle2(); 6 function clickHandle1(){ 7 alert("something clicked!"); 8 } 9 function clickHandle2(){ 10 alert("something clicked again!"); 11 } 12 </script>
這裡實際只會綁定clickHandle2方法,clickHandle1被後面的clickHandle2覆蓋掉。
開發過程中推薦使用DOM 0級事件處理程式或者DOM 2級事件處理程式,如果只有一個事件處理程式DOM 0級就足夠了,當然,如需綁定多個事件處理程式,則需使用DOM 2級事件處理程式。
為了屏蔽各瀏覽器之間的實現差異,推薦使用一些JavaScript庫來輔助完成事件綁定。推薦使用jQuery,針對不同的瀏覽器,可以使用統一的介面來完成這一過程。
參考:
js如何移除匿名函數的事件綁定 - https://www.cnblogs.com/sichaoyun/p/6776310.html