iT邦幫忙

2021 iThome 鐵人賽

DAY 17
0
自我挑戰組

邊工作邊進行前端學習之旅系列 第 17

[Day 17] JS - 冒泡事件 (Event Bubbling)

前言

延續昨天的事件監聽,一開始花了滿多時間在認識各個事件的使用方式,特別在後續專案實作上,認識更多的執行方式。不過對於基礎觀念不花費心力來理解它,永遠就是會弄不清楚,其中冒泡事件就是其中之一,從剛開始進入 JS 實作時,總是會不太清楚為什麼這裡要下 event.stopPropagation(),總以為是必須要寫上的,直到學習到冒泡事件 (Event Bubbling)才知道用意啊~

學習資源分享

  1. JavaScript DOM Tutorial #10 - Event Bubbling,以ul > li的列表來介紹綁定監聽事件,並以情況說明會發生什麼問題,該如何「捕獲」或「冒泡」特性來修正,藉此也可以深刻記得未來在做類似的功能時,要注意哪些地方。
  2. JavaScript Event Capture, Propagation and Bubbling - #JavaScript30 25/30,JavaScript30 的相關課程,影片不長但詳細地說明冒泡事件 (Event Bubbling)的運作機制。

從監聽事件開始

  • 建立監聽事件,主要有以下參數
    • 選擇要出現的事件:click,hover,hide,mouseover...
    • 中間為匿名 function,用來放入主要要做的功能
    • 布林值:由 Boolean 決定事件是以「捕獲」或「冒泡」機制執行,若不指定則預設為「冒泡」
var button = document.querySelector('.btn');
button.addEventListener('click',function(e){
  alert('Hello this is button');
},false)

JS中事件的三個階段

  1. 捕獲階段(Capture Phase):DOM 的事件會從(window) 開始往下尋找目標 (target)。是一個找尋過程
  2. 目標階段(Target Phase):到達事件目標(找到元素),就是到了目標階段。
  3. 冒泡階段(Bubbling):由事件目標依序向外傳遞,過程中觸發各別元素的監聽事件。(逐層往上傳遞,直到整個網頁的根節點,也就是 document->Window。)
  • 透過下圖,來更了解三階段:
    • 捕獲:從window逐步往下找尋目標。
    • 目標:找到目標為<td>
    • 冒泡:<td>被點擊時,事件會冒泡往上執行。

要如何控制捕獲或冒泡?

  • 透過addEventListener方法的最後一個參數phase(階段)來決定
    • false(冒泡事件,Event Bubbling)- 從指定元素往外層找
      • 當最內部的元素被觸發事件時,會先執行自己本身的事件處理函式,然後才會執行上層父母元素的事件處理函式。
    • true(捕獲事件,Event Capuring)- 從最外面找到指定元素
      • 當最內部的元素被觸發事件時,會先從最外圍的事件處理函式執行,依序到最後才是執行自己本身的處理函式。
    • 如果預設沒寫的話,就是false,也就是預設使用事件冒泡(bubbling)

js事件處理

事件冒泡會產生怎麼樣的行為

  • 事件點擊後,會一直冒泡上去

以例子來說明

  • 建立具有父層、子層關係的3個box
    • 並於3個div,都建立監聽事件=>點擊時,印出字樣box-3 is clicked

冒泡事件就是:

  • 當點擊box-3(最內層元素),會往上觸發父層的元素
    • 可以看到3->2->1被觸發
  • 當點擊box-2
    • 2->1被觸發
  • 當點擊box-1,就會只有box-1觸發,並印出box-1 is clicked!

  <div id="box-1">
    <h2>box-1</h2>
    <div id="box-2">
      <h2>box-2</h2>
      <div id="box-3">
        <h2>box-3</h2>
      </div>
    </div>
  </div>
  
  <script>
    $(function () {
      // 點擊3時,2也會觸發(這就是冒泡事件的特性),所以必須要停止冒泡行為,否則它會一直往上觸發。
      //他的順序是固定的3->2->1,從最裡面開始

      $('#box-3').click(function () {
        console.log("box-3 is clicked!");
      });
      $('#box-2').click(function () {
        console.log("box-2 is clicked!");
      })
      
      $('#box-1').click(function () {
        console.log("box-1 is clicked!");
      })


    })


  </script>

如何阻止事件冒泡

  • 透過阻止冒泡事件,確實只執行所點擊的元素。所以只要在該監聽事件函式內加入:e.stopPropagation()
    • 以下,選取到#box-3,並設定阻止冒泡的行為發生,就可以發現他只會出現 box-3 is clicked!
   $('#box-3').click(function (event) {
        //阻止冒泡的行為發生
        event.stopPropagation();
        console.log("box-3 is clicked!");
      });

參考資料:
[第七週] DOM - 事件傳遞機制:捕獲與冒泡、事件代理
重新認識 JavaScript: Day 14 事件機制的原理
DOM 的事件傳遞機制:捕獲與冒泡


上一篇
[Day 16] JavaScript 網頁事件處理
下一篇
[Day 18] JS - 變數提升Hoisting
系列文
邊工作邊進行前端學習之旅30

尚未有邦友留言

立即登入留言