Tech
    Cooking
    Baking
    Books
    About me

Back

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

更新時間: 2021/08/24

事件捕捉 (Event capturing)

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

graph TD window["Window"] --- document["Document"] window["Window"] -.-> document["Document"] document --- html["Element html"] document -.-> html["Element html"] html --- body["Element body"] html -.-> body["Element body"] body --- div["Element div"] body -.-> div["Element div"]

事件冒泡 (Event bubbling)

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

graph TD window["Window"] --- document["Document"] document["Document"] -.-> window["Window"] document --- html["Element html"] html["Element html"] -.-> document html --- body["Element body"] body["Element body"] -.-> html body --- div["Element div"] div["Element div"] -.-> body

事件傳遞順序

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

graph TD window["Window"] -- 1. capture --> document["Document"] document["Document"] -. 8. bubble .-> window["Window"] document -- 2. capture --> html["Element html"] html["Element html"] -. 7. bubble .-> document html -- 3. capture --> body["Element body"] body["Element body"] -. 6. bubble .-> html body -- 4. capture --> div["Element div"] div["Element div"] -. 5. bubble .-> body

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

常數
none 0
capturing 1
at target 2
bubbling 3

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:

資料來源