花一天時間研究完了DOM2級事件中addEventListener的執行機制,做爲開山第一帖,和你們講講多個addEventListener同時添加時的執行前後規律:
javascript
如圖,你們都知道,W3c的DOM事件觸發分爲三個階段:
①、事件捕獲階段,即由最頂層元素(通常是從window元素開始,有的瀏覽器是從document開始,至於其中的差異我稍後會更新)開始,逐次進入dom內部,最後到達目標元素,依次執行綁定在其上的事件
②、處於目標階段,檢測機制到達目標元素,按事件註冊順序執行綁定在目標元素上的事件。
③、事件冒泡階段,從目標元素出發,向外層元素冒泡,最後到達頂層(window或document),依次執行綁定再其上的事件。java
在addEventListener中,利用第三個參數控制其是從哪一個階段開始,「true」是從捕獲階段開始,而「false」則是跳過捕獲階段,從冒泡階段開始。
看一個簡單的例子:瀏覽器
<script type="text/javascript"> window.onload=function(){ var outer = document.getElementById("outer"); var inner = document.getElementById('inner'); outer.addEventListener("click", function(){ alert("1"); } , true); inner.addEventListener("click", function(){ alert("2"); } , true); outer.addEventListener("click", function(){ alert("3"); } ,false) } </script> <body> <div id="outer"> <div id="inner"></div> </div> </body>
在這個例子裏,若是咱們點擊內層元素inner,那麼處於捕獲階段的1最早彈出,接下來是目標元素2彈出,最後是處於冒泡階段的3彈出,即:1,2,3.
即便在代碼裏變換三個綁定事件的順序,只要點擊的是inner,這個執行順序就不會變。dom
那麼問題來了,若是點擊的是外層outer的話呢?spa
要明白這個問題,咱們必須明確一點:目標事件在哪一層,事件流就在哪一層迴流,即便在outer事件下還有許多子孫節點,事件流都不會在outer以後往內流,此時,inner上的事件不會被觸發,所以在這段代碼中,只會彈出1和3。code
那麼這兩個數字哪一個先彈呢?因爲此時事件處於第二階段,即「處於目標階段」,彈出順序取決的也再也不是捕獲或冒泡,而是誰在代碼中先註冊,所以,在這段代碼中,彈出的是:1→3.blog
綜上所述,事件在DOM中的執行順序爲:外層捕獲事件→內層捕獲事件→先註冊的目標事件→後註冊的目標事件→內層冒泡事件→外層冒泡事件事件
讓咱們再看個例子來加深這個概念:圖片
<script type="text/javascript"> window.onload=function(){ var outer = document.getElementById("outer"); var inner = document.getElementById('inner'); var oBox=document.getElementById('box'); oBox.addEventListener("click",function(){ alert('1'); },true) oBox.addEventListener("click",function(){ alert('4'); },false) outer.addEventListener("click", function(){ alert("2"); }, true); inner.addEventListener("click",function(){ alert('3.2') },false) inner.addEventListener("click", function(){ alert("3.1"); }, true); } </script> <body> <div id="box"> <div id="outer"> <div id="inner"></div> </div> </div> </body>
在這段代碼裏,box上的捕獲事件最早執行,而後是outer上的捕獲事件,而後是inner上先註冊的事件,而後是inner上後註冊的事件,最後是box上的冒泡事件
彈出順序爲:1→2→3.2→3.1→4 ip
補充一點,在ie8-中,因爲addEventLister不起做用,咱們使用attachEvent方法來綁定事件,此時在第二階段,也就是處於目標階段,若是目標元素上綁定了兩個事件,那麼其執行順序和addEventLister相反:誰後註冊誰先執行。