JS趴趴往上走-DOM傳遞機制

Event Bubbling & Event Capturing

要了解捕獲與冒泡機制之前首先我們要知道事件是怎麼處理的

大家還記得DOM是一層一層下來的

 <html>
  <head>
    <title>網頁標題</title>
  </head>

  <body>
    <h1>Header</h1>
    <a href="#">快速連結</a>
  </body>

 </html>


對應的的圖片:




而他們重疊的樣子就是






所以當你點擊目標(target)時,在這邊我們假設點擊了<a>連結,其實除了<a>被點擊之外,包含它的<body>其實也被點擊了哦,<html>document也被點擊了,會一層一層往上找
所以我們可以知道點擊了一個<a>,有包覆它的元素也會跟著被點擊,可以說是整個網頁都被點擊了!


那麼除了目標之外,有包覆著他的都會被點擊,那它們是誰先傳遞續訊息呢?

DOM在傳遞訊息順序有兩種方法:

事件冒泡 Event Bubbling
事件捕獲 Event Capturing


Event Bubbling

事件冒泡是指,當您點擊目標元素後,會一層一層往上傳遞,直到最上面的根結點,就是我們的document

以下面範例來說:

 <html>
  <head>
    <title>網頁標題</title>
  </head>

  <body>
   <ul>
     <li></li>
     <li></li>
     <li><a href="#"></a></li>
    </ul>
  </body>

 </html>


當我們點擊<a>,而冒泡機制就會是

<a><li><ul><body><html><document>
逐漸往上觸發


Event Capturing

事件捕獲就和事件冒泡相反,是從上往下觸發
所以以上範例來講,點擊目標<a>它會是

<document><html><body><ul><li><a>

觸發優先順序

事件捕獲和事件冒泡兩個機制對於事件都會執行,沒有特別依賴哪種,但當兩種機制若是一起觸發的話事件會

先捕獲,再冒泡

我們看之前addEventListener()範例(建議點進去看console.log())


當兩種事件都被觸發時,外層捕獲會優先執行,再到內層,這邊提醒:內層對於點擊的目標是沒有分順序的!誰程式碼優先,就先執行,之後再換外層冒泡執行


終止捕獲、冒泡

現在我們知道點擊內部,外面也會被觸發,那怎麼阻止這種事發生,就可以使用Event.stopPropagation()


Event.stopPropagation():可以阻止當前事件繼續進行捕獲及冒泡階段的傳遞


以下範例來看(建議點進去看console.log())
當你的Event.stopPropagation()放在哪邊,事件的傳遞就斷在哪裡,不會繼續往下傳遞
See the Pen
Event.stopPropagation()
by yanennn (@yennnnn)
on CodePen.




假如:console.log("我是外面捕獲!!!")放置Event.stopPropagation(),當點擊我在裡面的div,你會發現console.log()只會顯示"我是外面捕獲!!!"

因為當點擊目標時,你上面的也會跟著點擊,以先捕獲再冒泡,所以會先顯示"我是外面捕獲!!!",接著"我是外面捕獲!!!"有放置Event.stopPropagation(),所以傳遞斷掉了,故只顯示"我是外面捕獲!!!"

所以說,若你是把Event.stopPropagation()放在console.log('我是裡面冒泡!!!');或者 console.log('我是裡面捕獲!!!');就會依序得到"我是外面捕獲!!!""我是裡面冒泡!!!""我是裡面捕獲!!!","我是外面冒泡!!!"因為被中斷了所以不會顯示


Event.stopPropagation()(建議點進去看console.log())只能中斷你想中斷的那個節點而已,若是你想要讓其他同一層級的也不要被執行,可以改用e.stopImmediatePropagation();


這邊提醒,同一層級是按照程式碼優先依序執行的,若你Event.stopImmediatePropagation();寫在同層級的最後一個,前面一樣還是會被執行哦



資料來源:
https://blog.techbridge.cc/2017/07/15/javascript-event-propagation/
https://ithelp.ithome.com.tw/articles/10191970?sc=iThelpR

留言