[解惑]JavaScript事件機制


群里童鞋問到關於事件傳播的一個問題:“事件捕獲的時候,阻止冒泡,事件到達目標之后,還會冒泡嗎?”。

初學 JS 的童鞋經常會有諸多疑問,我在很多 QQ 群也混了好幾年了,耳濡目染也也收獲了不少,以后會總結下問題的結論,順便說說相關知識的擴展~

如果貿然回答還會冒泡,這不太好的,稍微嚴謹點考慮 0級 DOM 事件模型的話,這個答案是否定的。但是在 2級 DOM 事件模型中,答案是肯定的,這個問題值得探討記錄下。

本文地址:http://www.cnblogs.com/hustskyking/p/problem-javascript-event.html 

一、問題結論

netscape 和 微軟 曾經的戰爭還是比較火熱的,當時, netscape 主張捕獲方式,微軟主張冒泡方式。后來 w3c 采用折中的方式,平息了戰火,制定了統一的標准——先捕獲再冒泡。

 事件的觸發有三個階段
  1. document 往事件觸發地點,捕獲前進,遇到相同注冊事件立即觸發執行
  2. 到達事件位置,觸發事件(多謝 @糖果果 指出 問題 ,@update 14/2/19 如果該處既注冊了冒泡事件,也注冊了捕獲事件,按照注冊順序執行)
  3. 事件觸發地點往 document 方向,冒泡前進,遇到相同注冊事件立即觸發

這么說很多人比較迷糊,我們在注冊事件的時候,通常使用的是 捕獲 或者 冒泡 的 一種:

obj.addEventListener("click", func, true); // 捕獲方式
obj.addEventListener("click", func, false); // 冒泡方式

事件只會因為捕獲或者冒泡觸發一次。舉個栗子:

點擊 s2,結果是:

因為這里采用的是捕獲模式,從 document 往 s2 走,依次發現 s1 和 s2 都有注冊捕獲事件,於是便觸發了,然后冒泡,沒找到冒泡事件,不執行任何操作。如果將 true 改成 false,可以看到結果相反。為了更好的讓你理解整個事件機制,我給他們的捕獲和冒泡模式下都注冊事件:

結果真是太清晰了:

 

二、誤區

指出兩個誤區。

1. 在同一個對象上注冊事件,並不一定按照注冊順序執行

這一點,從上面的例子可以看出,你隨便打亂四個事件綁定的順序,結果一般不變!出現這樣結果的原因是存在捕獲模式和冒泡模式。但是值得注意的是,下面 #5樓 @糖果果 提出的問題,之所以如此是因為事件目的地節點既綁定了冒泡事件也綁定了捕獲事件,此時的執行順序按照綁定的先后順序執行(情況比較少見)。

2.event.stopPropagation();就是阻止事件的冒泡

這個表述不能說他錯誤,但是是不完整的,他除了阻止事件的冒泡,還阻止事件的繼續捕獲,簡而言之就是阻止事件的進一步傳播。下面的例子可以看到:

結果是輸出了 s1.

 

三、拓展

1. stopImmediatePropagation 的使用

這玩意兒是 w3c 的東西,使用的也不是特別多,我們知道 stopPropagation 可以阻止事件的進一步傳播,但是他阻止不了該元素上綁定的其他函數的執行,比如我們在 obj 上綁定了 func1 和 func2,如果我們在 func1 中使用了 stopPropagation ,那 func2 依然還是會執行出來。倘若這里使用 stopImmediatePropagation,結果就不一樣了,他不僅阻止事件的傳播,還阻止 func2 的執行。如:

結果是:

而改成evt.stopImmediatePropagation();之后,阻止了第二個監聽事件的觸發:

結果是:

2. setCapture 和 releaseCapture

這兩個是 IE 下的事件綁定函數,只要我們在某個元素上 setCapture 了,那么你在任何地方的鼠標操作(mouseXXX之類的動作)都會在這個元素上觸發(前提是你在這個元素上綁定了事件),releaseCapture 或者本窗口失去聚焦才會釋放這個綁定~

 

四、小結

對於此類知識的學習,應該查閱官方點的文檔,或者看看《JavaScript權威指南》的解說,后期會經常整理諸如此類的問題。若有疑問,可以在下方評論中提出。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM