JavaScript事件機制,也有讓人深思的東西。在一開始未深刻了解,我頭腦裏有幾個問題發出:javascript
1. 自下而上(冒泡)事件怎麼寫,自上而下(捕獲)又是怎麼寫?php
2. 捕獲型和冒泡型同時設置,誰生效?html
3. 冒泡可以阻止,那捕獲可以阻止嗎?java
4. jquery的on或bind是冒泡,仍是捕獲?jquery
5. 兩種事件方式的應用場景是?this
示例spa
<!DOCTYPE HTML> <html lang="en-US"> <head> <meta charset="UTF-8"/> <title>Events</title> <script type="text/javascript" src="jquery-3.0.0.js"></script> <style> html,body{ width:100%; height:100%; padding: 0; margin: 0; } div{ float:left; width: 200px; height:200px; border:1px solid blue; } p{ width: 100px; height:100px; border:1px solid red; } </style> </head> <body id="body"> <div id="J_d0"> 0<p id="J_p0"></p> </div> <div id="J_d1"> 1<p id="J_p1"></p> </div> <div id="J_d2"> 2<p id="J_p2"></p> </div> <div id="J_d3"> 3<p id="J_p3"></p> </div> <div id="J_d4"> 4<p id="J_p4"></p> </div> </body> <script> var body = document.getElementById('body'); body.addEventListener('click', hello, true); //當爲false時,所有在最後執行。 bindEvent_d_p(0,true,true); //點擊p,輸出 //i am body //i am J_d0 //i am J_p0 bindEvent_d_p(1,false,true); //點擊p,輸出 //i am body //i am J_p1 //i am J_d1 bindEvent_d_p(2,false,false); //點擊p,輸出 //i am body //i am J_p2 //i am J_d2 bindEvent_d_p(3,true,false); //點擊p,輸出 //i am body //i am J_d3 //i am J_p3 $("#J_d4").on("click", hello); $("#J_p4").on("click", hello); //點擊p,輸出 //i am body //i am J_p4 //i am J_d4 function bindEvent_d_p(index, d_useCapture, p_useCapture){ var d = document.getElementById('J_d'+index); var p = document.getElementById('J_p'+index);
//第三個參數,指定事件是在捕獲階段仍是冒泡階段執行。
d.addEventListener('click', hello, d_useCapture);
p.addEventListener('click', hello, p_useCapture);
} function hello() { console.log("i am " + this.id); } </script> </html>
這裏關鍵的是第三個參數。W3CSchool解釋爲「指定事件是否在捕獲或冒泡階段執行」,我以爲這個說明會讓人誤會,搞得像捕獲或冒泡均可以不選的樣子。但其實不是,只是二選一,因此最好解釋爲「指定事件是在捕獲階段仍是冒泡階段執行」。.net
定義code
JavaScript的事件是以一種流(迴環流)的形式存在的,一個事件會有多個元素同時響應。以下圖:htm
PS:圖例來自http://www.nowamagic.net/javascript/js_EventAnalysis.php
這個圖很是清楚的說明的事件的執行順序,徹底能夠解釋示例中的結果。事件一直從window往觸發目標元素流,當父或祖先捕獲事件時,就先執行,否則就在冒泡階段執行,直到window。
Q&A
1. 自下而上(冒泡)事件怎麼寫,自上而下(捕獲)又是怎麼寫?
當須要冒泡時,第三參數設爲false就行;
當須要捕獲時,第三參數設爲true就行;
2. 捕獲型和冒泡型同時設置,誰生效?
按第三參數的設置,只有二選一,並不存在能夠同時設置狀況。
3. 冒泡可以阻止,那捕獲可以阻止嗎?
冒泡事件是可以阻止,e.stopPropagation();,你們是比較清楚的,一樣的捕獲事件也是能阻止的。
其實就是當先觸發的事件是在捕獲過程的,阻止了事件傳播,就是捕獲阻止,當在冒泡過程當中阻止,就是冒泡阻止。
結果就是,事件流再也不繼續流了,不管是往下仍是往上。
4. jquery的on或bind是冒泡,仍是捕獲?
通過上面示例能夠驗證, jquery的on或bind是冒泡執行的。
另外在jquery3.0.0的源碼4943行地方:
// Init the event handler queue if we're the first if ( !( handlers = events[ type ] ) ) { handlers = events[ type ] = []; handlers.delegateCount = 0; // Only use addEventListener if the special events handler returns false if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { if ( elem.addEventListener ) { elem.addEventListener( type, eventHandle ); } } }
這裏能夠很明顯看到,事件的註冊並無傳第三個參數,因此 jquery的on或bind確定是冒泡執行的。
5. 兩種事件方式的應用場景是?
額,這個問題並很差回答,就具體問題,具體分析了。
總結
小小的往細處想,居然發現我其實有些細節並沒明白,共勉。
本文爲原創文章,轉載請保留原出處,方便溯源,若有錯誤地方,謝謝指正。