回想起自己學習事件模式那會兒歉铝,怎么都記不住事件的傳播流程和 addEventListener 的設置細節(jié),后來發(fā)現(xiàn)好的圖片更能能幫助我們理解邏凑耻,所以做了一個 GIF太示。
事件傳播模式
假設我們現(xiàn)在有三個DOM
節(jié)點,并且假設 div 為根節(jié)點香浩。(通常事件的捕獲會從根節(jié)點開始)
然后我們?yōu)檫@些DOM
節(jié)點設置好監(jiān)聽类缤。
// 設置第三個參數(shù)為 true 則在捕獲階段觸發(fā)
div.addEventListener('click', null, true);
p.addEventListener('click', null, true);
span.addEventListener('click', null, true);
span.addEventListener('click', null);
p.addEventListener('click', null);
div.addEventListener('click', null);
現(xiàn)在我們點擊span
,那么click
事件會被觸發(fā)邻吭,事件會從div
進入捕獲階段餐弱,從父級向子級傳遞,到達事件目標后進入冒泡階段,從子級像父級傳遞膏蚓。
(click)span
=> div -> p -> span -> span -> p -> div
如果我們點擊p
瓢谢,那么事件目標為p
元素,事件從div
元素開始捕獲驮瞧,并從p
元素處折返變?yōu)槊芭荨?/p>
(click)p
=> div -> p -> p -> div
多次綁定
如果在一個節(jié)點上多次綁定同一個事件的監(jiān)聽氓扛,它們會按照事件傳播流程進行(先捕獲后冒泡),如果所處流程一樣則按照先綁定先觸發(fā)的原則论笔。
// 設置第三個參數(shù)為 true 則在捕獲階段觸發(fā)
div.addEventListener('click', null, true) // #1
div.addEventListener('click', null) // #2
div.addEventListener('click', null, true) // #3
p.addEventListener('click', null, true);
p.addEventListener('click', null);
(click)p
=> div#1 -> div#3 -> p -> p -> div#2
雖然申明的順序是div#1
div#2
div#3
采郎,但是捕獲先于冒泡,所以 div#1
div#3
依次觸發(fā)狂魔,而div#2
在冒泡過程中觸發(fā)蒜埋。
stopPropagation
這是Event
對象的一個方法,用來阻止事件進一步傳播最楷。
// 設置第三個參數(shù)為 true 則在捕獲階段觸發(fā)
// #1
div.addEventListener('click', function (event) {
event.stopPropagation();
}, true)
div.addEventListener('click', null) // #2
div.addEventListener('click', null, true) // #3
p.addEventListener('click', null, true);
p.addEventListener('click', null);
(click)p
=> div#1 -> div#3
使用了stopPropagation()
之后整份,事件就不能進一步傳播了,即使是在div
上籽孙,捕獲和冒泡被認為是兩個步驟皂林,所以在捕獲階段傳播被阻止時同節(jié)點上的冒泡也不會觸發(fā)。
stopImmediatePropagation
這是Event
對象的一個方法蚯撩,一旦調用這個方法,則該元素上未觸發(fā)的監(jiān)聽都不會被觸發(fā)烛占,事件也不會進一步傳播胎挎。
現(xiàn)在我們在div
上再多增加一個事件監(jiān)聽,并把stopImmediatePropagation
添加在捕獲事件中第二個觸發(fā)的監(jiān)聽上忆家。
// 設置第三個參數(shù)為 true 則在捕獲階段觸發(fā)
div.addEventListener('click', null, true) // #1
div.addEventListener('click', null) // #2
// #3
div.addEventListener('click', function (e) {
e. stopImmediatePropagation();
}, true)
div.addEventListener('click', null, true) // #4
p.addEventListener('click', null, true);
p.addEventListener('click', null);
(click)p
=> div#1 -> div#3
使用了stopImmediatePropagation()
之后犹菇,連當前節(jié)點中等待觸發(fā)的監(jiān)聽都沉默了。
擴展閱讀
在比較新的瀏覽器中芽卿,addEventListener
支持更多參數(shù)配置揭芍,第三個參數(shù)類型支持object
。
target.addEventListener(type, listener[, options]);
這個 options 支持三個字段
- capture
Boolean
是否在捕獲模式觸發(fā) - once
Boolean
是否僅觸發(fā)一次 - passive
Boolean
是否使用被動模式
這里展示一下once
的效果
// 設置第三個參數(shù)為 true 則在捕獲階段觸發(fā)
div.addEventListener('click', null, true);
p.addEventListener('click', null, true);
span.addEventListener('click', null, true);
span.addEventListener('click', null);
p.addEventListener('click', null, {once: true}); // 在冒泡階段只觸發(fā)一次
div.addEventListener('click', null);
(click)span
=> div -> p -> span -> span -> p -> div
(click)span
=> div -> p -> span -> span -> div
Demo
羅小黑寫寫文字
如果喜歡文章 請留下一個贊~
如果喜歡文章 分享給更多人~自由轉載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證)
轉載時請保留原文鏈接 以保證可及時獲取對文章的訂正和修改