事件捕捉 &事件冒泡 (Event capturing & event bubbling)

歡迎到我的Blog看這篇文章~

https://myblog-jeserlin.vercel.app/tech/event-bubbling-event-capturing

事件捕捉 (Event capturing)

事件傳遞的順序是從上到下,由最外層的WindowDocument最後到事件發起的Element

事件冒泡 (Event bubbling)

而事件冒泡(Event bubbling)則是相反,事件傳遞的順序是從下到上,由事件發起的ElementDocument最後再到Window

事件傳遞順序

把以上兩種機制合在一起看的話,事件傳遞的順序就會是由上而下由下而上, 也就是說先捕捉後冒泡: 而這是因為當年兩大龍頭 Microsoft 跟 Netscape 分別提出了不同的處理順序,最後 W3C 決定把兩種機制合在一起同時支援並且把 先捕捉後冒泡設定為預設行為。因此當一個事件發生時,他的傳遞順序會是如圖:

同樣我們也可以從事件傳遞的階段常數(Event Phase)了解到他的順序:

常數
none0
capturing1
at target2
bubbling3

EventTarget.addEventListener()

target.addEventListener(type, listener, useCapture)

addEventListener是大家很常使用的一個api, 但是我們很少會注意到第三個參數上:

  • useCapture (optional): boolean, default是false,用來指定這個event是使用捕捉(capturing)還是冒泡(bubbling)

事件冒泡 (useCapture: false, Event bubbling)

在這個範例中,我們使用useCapture的default value,試著點擊Layer可以看到event是使用 冒泡(bubbling)機制:

事件捕捉 (useCapture: true, Event capturing)

而以下的範例是使用useCapture: true,試著點擊Layer可以看到event是使用 捕捉(capturing)機制:

Event.stopPropagation()

然而在實際的情況下,我們不一定會希望事件一層一層地被傳遞,這時候我們可以使用Event.stopPropagation()來阻止當前事件繼續進行捕捉或冒泡。

舉個例子來說,我們有一個button他的上面還有另一個 Element用來控制value是asc還是desc。我們預期的結果是點擊sort type的時候,他會切換成ascdesc但不會觸發button的event,只有在點擊button的時候才會觸發button上的event:

資料來源