事件傳遞
說明事件傳遞的流程及事件三個階段及阻止事件冒泡
“JavaScript 是一個事件驅動 (Event-driven) 的程式語言,當瀏覽器載入網頁開始讀取後,雖然馬上會讀取 JavaScript 事件相關的程式碼,但是必須等到「事件」被觸發(如使用者點擊、按下鍵盤等)後,才會再進行對應程式的執行。””–重新認識 JavaScript: Day 14 事件機制的原理
事件流程 Event Flow
以div元素說明:
1 | <style> |
在點擊(Click)黃色 C div時,我們等同於點擊了紅色B div、綠色的A div**(因為A div包裹著B div,B div包裹著C div),也可視為點擊了整個網頁,
因此網頁元素接收事件的順序**為事件流程。
事件的三個階段
捕獲階段(Capture Phase)
事件從根節點流向目標節點,途中流經各個DOM節點,在各個節點上觸發捕獲事件,直到達到目標節點。(由外而內)
目標階段(Target Phase)
事件到達目標節點時,就到了目標階段,事件在目標節點上被觸發
冒泡階段(Bubbling Phase)
事件在目標節點上觸發後,不會終止,一層層向上冒,回溯到根節點。(由內而外)
經過上面三個階段解釋,我們以W3C DOM Event的圖片來看整體流程
利用事件監聽EventTarget.addEventListener()做階段監聽
明白整體流程後,我們由剛才舉例事件流程的範例繼續延伸,釐清我們的點擊過程,以驗證捕獲過程及冒泡過程的先後順序:
我們預期點擊黃色方塊(C div)反應,因此撰寫事件監聽
- Html及Css上面程式撰寫了,因此本次著重撰寫在javascript上:點擊後反應為:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27var div = document.getElementById("A");
var div = document.getElementById("B");
var div = document.getElementById("C");
//參數一般無撰寫會默認是false,為事件冒泡"模式",
//這裡為求清楚撰寫出false
A.addEventListener('click', function (event) {
console.log('A');
},false);
B.addEventListener('click', function (event) {
console.log('B');
},false);
C.addEventListener('click', function (event) {
console.log('C');
},false);
//參數設为true為事件捕獲"模式"
A.addEventListener('click', function (event) {
console.log('A');
}, true);
B.addEventListener('click', function (event) {
console.log('B');
}, true);
C.addEventListener('click', function (event) {
console.log('C');
}, true);
注意!code內,我們特意撰寫冒泡過程為先,但是跑出的反應卻是補獲過程先啟動,
因此我們明白:
捕獲及冒泡事件皆會執行,先捕獲階段,再來是冒泡階段
阻止事件冒泡
也可以稱為取消事件傳遞,因為上述事件流程中,我們在點擊時會同時觸發外層的div,我們不希望這樣的冒泡事件發生,因此如何中斷事件冒泡傳遞,可使用方法為event.stopPropagation()
:
- 以上述相同的javascript code 繼續撰寫,以冒泡過程做示範:點擊後,事件流程將會停留在B階段
1
2
3
4
5
6
7
8
9
10
11A.addEventListener('click', function (event) {
console.log('A');
},false);
B.addEventListener('click', function (event) {
// 加上阻止事件,另外funtion(event)可縮寫為function(e),但初學者建議寫完整。
event.stopPropagation();
console.log('B');
},false);
C.addEventListener('click', function (event) {
console.log('C');
},false);
參考資料:事件的三個階段:捕獲階段目標階段冒泡階段