iT邦幫忙

2022 iThome 鐵人賽

DAY 25
0
自我挑戰組

JavaScript 30天挑戰 自學筆記系列 第 25

JS30 自學筆記 Day25_Event Capture, Propagation, Bubbling and Once

  • 分享至 

  • xImage
  •  

今日任務: 認識DOM 事件傳遞方式

事件傳遞方式

事件傳遞方式總共分為三大階段:

  • 捕獲階段 (Capture Phase)
    在捕獲階段,DOM事件會從根結點 (window) 開始往下一層一層傳遞到目標 (target),這個過程稱為捕獲階段 (CAPTURING_PHASE)。
  • 目標階段 (Target Phase)
    target為實際點擊的對象,在傳遞事件到target的時候,就會是目標階段 (AT_TARGET)。
    到達目標階段後,會依照addEventListener()的第三個參數註冊順序觸發事件。
  • 冒泡階段 (Bubbling Phase)
    事件再從原路傳遞回去的過程,就是冒泡階段 (BUBBLING_PHASE)。

認識事件處理addEventListener()

語法

element.addEventListener(event, function, useCapture)
element.addEventListener(event, function, options)
  • event: 監聽事件名稱(詳細Dom事件)。
  • function: 事件觸發時執行的函式。
  • 第三個參數:(指定這個事件要在什麼階段觸發)
  1. useCapture,可用boolean值決定事件傳遞方式,預設為false監聽冒泡階段 (Bubbling Phase),true為監聽捕獲階段 (Capture Phase)。
  2. options: 決定事件傳遞方式。可用的選項有:
    • capture:
      boolean值,true為監聽捕獲階段 (Capture Phase),預設為 false。
    • once:
      boolean值,true為只監聽一次,預設為 false。
    • passive:
      boolean值,true為無法在函式使用preventDefault(),預設為false。
      除了Safari 和 Internet Explorer,其他瀏覽器中,對於 wheel, mousewheel, touchstart 和 touchmove事件,預設為 true。 查看詳細:使用被動偵聽器提高滾動性能

示範:

可以使用e.eventPhase查看目前事件正在什麼階段。
e.eventPhase:事件(Event)當前正在事件流的哪個階段。

  • Event.NONE (0): 目前未處理該事件。
  • Event.CAPTURING_PHASE (1): 事件正在捕獲階段 (Capture Phase)。
  • Event.AT_TARGET (2): 事件正在目標階段 (Target Phase)。
  • Event.BUBBLING_PHASE (3): 事件正在冒泡階段 (Bubbling Phase)。

HTML

<div class="one">
    <div class="two">
        <div class="three"></div>
    </div>
</div>

冒泡階段觸發function

當沒有第三個參數時,預設是冒泡階段觸發function,
所以當點擊的時候,瀏覽器會從最外面偵測到最裡面,抓到你點擊的地方是哪裡,
找到target(這裡為three)後,由內往外傳遞事件觸發function

const divs = document.querySelectorAll('div');

divs.forEach((div) =>
    div.addEventListener('click', logText)
);

function logText(e) {
    console.log(this.classList.value, e.eventPhase);
}

點了最裡面的,但是會連父層的都顯示出來

捕獲階段觸發function

const divs = document.querySelectorAll('div');

divs.forEach((div) =>
    div.addEventListener('click', logText, {
        capture: true,
    })
);

function logText(e) {
    console.log(this.classList.value, e.eventPhase);
}

stopPropagation()停止事件傳遞

const divs = document.querySelectorAll('div');

divs.forEach((div) =>
    div.addEventListener('click', logText, {
        capture: false,
    })
);

function logText(e) {
    console.log(this.classList.value, e.eventPhase);
    e.stopPropagation();
}


將capture改為true

once 綁定事件只會觸發一次

const divs = document.querySelectorAll('div');

divs.forEach((div) =>
    div.addEventListener('click', logText, {
        capture: false,
        once: true,
    })
);

function logText(e) {
    console.log(this.classList.value, e.eventPhase);
}


今日學習到的:
事件傳遞方式總共分為三大階段:

  • 捕獲階段 (Capture Phase)
    在捕獲階段,DOM事件會從根結點 (window) 開始往下一層一層傳遞到目標 (target),這個過程稱為捕獲階段 (CAPTURING_PHASE)。
  • 目標階段 (Target Phase)
    target為實際點擊的對象,在傳遞事件到target的時候,就會是目標階段 (AT_TARGET)。
    到達目標階段後,會依照addEventListener()的第三個參數註冊順序觸發事件。
  • 冒泡階段 (Bubbling Phase)
    事件再從原路傳遞回去的過程,就是冒泡階段 (BUBBLING_PHASE)。
  • 認識事件處理addEventListener()
    • event: 監聽事件名稱。
    • function: 事件觸發時執行的函式。
    • 第三個參數:(指定這個事件要在什麼階段觸發)
    1. useCapture,可用boolean值決定事件傳遞方式,預設為false監聽冒泡階段 (Bubbling Phase),true為監聽捕獲階段 (Capture Phase)。
    2. options: 決定事件傳遞方式。可用的選項有:
      • capture:
        boolean值,true為監聽捕獲階段 (Capture Phase),預設為 false。
      • once:
        boolean值,true為只監聽一次,預設為 false。
      • passive:
        boolean值,true為無法在函式使用preventDefault(),預設為false。
        除了Safari 和 Internet Explorer,其他瀏覽器中,對於 wheel, mousewheel, touchstart 和 touchmove事件,預設為 true。 查看詳細:使用被動偵聽器提高滾動性能
  • e.eventPhase:事件(Event)當前正在事件流的哪個階段。
    • Event.NONE (0): 目前未處理該事件。
    • Event.CAPTURING_PHASE (1): 事件正在捕獲階段 (Capture Phase)。
    • Event.AT_TARGET (2): 事件正在目標階段 (Target Phase)。
    • Event.BUBBLING_PHASE (3): 事件正在冒泡階段 (Bubbling Phase)。

效果連結:連結

參考連結:
EventTarget.addEventListener()
Javascript 中的 DOM 事件傳遞機制:捕獲與冒泡 (capturing and bubbling)
DOM 的事件傳遞機制:捕獲與冒泡 - TechBridge 技術共筆部落格


上一篇
JS30 自學筆記 Day24_Sticky Nav
下一篇
JS30 自學筆記 Day26_Stripe Follow Along Dropdown
系列文
JavaScript 30天挑戰 自學筆記30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言