#每日一記#經過 GIF 理解 addEventListener、捕獲和冒泡

每日一記 - 但並不日更

回想起本身學習事件模式那會兒,怎麼都記不住事件的傳播流程和 addEventListener 的設置細節,後來發現好的圖片更能能幫助咱們理解邏,因此作了一個 GIF。javascript

事件傳播模式

假設咱們如今有三個DOM節點,而且假設 div 爲根節點。(一般事件的捕獲會從根節點開始)java

div -> p -> span

而後咱們爲這些DOM節點設置好監聽。瀏覽器

// 設置第三個參數爲 true 則在捕獲階段觸發
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);
複製代碼

如今咱們點擊span,那麼click事件會被觸發,事件會從div進入捕獲階段,從父級向子級傳遞,到達事件目標後進入冒泡階段,從子級像父級傳遞。學習

(click)span => div -> p -> span -> span -> p -> divspa

普通流程

若是咱們點擊p,那麼事件目標爲p元素,事件從div元素開始捕獲,並從p元素處折返變爲冒泡。code

(click)p => div -> p -> p -> divcdn

普通流程

屢次綁定

若是在一個節點上屢次綁定同一個事件的監聽,它們會按照事件傳播流程進行(先捕獲後冒泡),若是所處流程同樣則按照先綁定先觸發的原則。對象

// 設置第三個參數爲 true 則在捕獲階段觸發
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#2blog

屢次綁定

雖然申明的順序是div#1 div#2 div#3,可是捕獲先於冒泡,因此 div#1 div#3依次觸發,而div#2在冒泡過程當中觸發。事件

stopPropagation

這是Event對象的一個方法,用來阻止事件進一步傳播。

// 設置第三個參數爲 true 則在捕獲階段觸發
// #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

使用了stopPropagation()以後,事件就不能進一步傳播了,即便是在div上,捕獲和冒泡被認爲是兩個步驟,因此在捕獲階段傳播被阻止時同節點上的冒泡也不會觸發。

stopImmediatePropagation

這是Event對象的一個方法,一旦調用這個方法,則該元素上未觸發的監聽都不會被觸發,事件也不會進一步傳播。

如今咱們在div上再多增長一個事件監聽,並把stopImmediatePropagation添加在捕獲事件中第二個觸發的監聽上。

// 設置第三個參數爲 true 則在捕獲階段觸發
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

使用了stopImmediatePropagation()以後,連當前節點中等待觸發的監聽都沉默了。

擴展閱讀

在比較新的瀏覽器中,addEventListener支持更多參數配置,第三個參數類型支持object

target.addEventListener(type, listener[, options]);

這個 options 支持三個字段

  • capture Boolean 是否在捕獲模式觸發
  • once Boolean 是否僅觸發一次
  • passive Boolean 是否使用被動模式

這裏展現一下once的效果

// 設置第三個參數爲 true 則在捕獲階段觸發
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}); // 在冒泡階段只觸發一次
div.addEventListener('click', null);
複製代碼

(click)span => div -> p -> span -> span -> p -> div

(click)span => div -> p -> span -> span -> div

once

Demo

JSbin

羅小黑寫寫文字

若是喜歡文章 請留下一個贊~ 若是喜歡文章 分享給更多人~

掘金中關注我 在簡書中關注我

自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證) 轉載時請保留原文連接 以保證可及時獲取對文章的訂正和修改

相關文章
相關標籤/搜索