iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 22
2
自我挑戰組

JavaScript 試煉之旅系列 第 22

JavaScript 捕捉(capturing)與氣泡(bubbling)

  • 分享至 

  • xImage
  •  

今天要學習的部分是關於 DOM 的傳遞機制:捕捉與氣泡

在切入今日的主題之前,先快速了解一下 addEventListener 的語法。

addEventListener

透過這個語法,我們可以將事件綁定在某個 HTML 元素上,並透過觸發的條件(如滑鼠點擊、按下鍵盤某一個按鍵等)進而得到需求的資訊並執行我們設定的行為。

target.addEventListener(type, listener[, options]);
  • type : 表示要觸發的方式,例如 clickkeydown 等。
  • listener: 會是一個函式,用於當條件觸發時需要做的任務
  • options: 條件觸發時決定是在捕捉或氣泡階段執行。預設為 false ,此時表示於氣泡階段執行; true 則為捕捉階段。

來看看 addEventListener 的測試例子:

<style>
.box{
  width:100px;
  height:100px;
  background:#ccc;
}
</style>

<div class="box"></div>
const box = document.querySelector('.box');
box.addEventListener('click',test,true);

function test(e){
  console.log(e)
}

上述就是一個透過 addEventListener 語法而設計的監聽事件,被監聽的對象是 <div> 元素,觸發條件為 click (滑鼠點擊時才觸發),而作為監聽事件的 test 函式,會傳入一個 e 的參數,這個參數用於接收當事件被觸發時,可以獲得的對應訊息。

捕捉與氣泡

接下來要進入主題,關於捕捉與氣泡的規範可以到 w3c event-flow 詳讀,有著更詳細的圖例。

而這裡為了搭配測試例子,所以簡化了 DOM 的結構。

先直接來看圖,並透過圖貫穿後續的篇幅:

Day22-1

上圖為接下來程式碼的 DOM 結構,並標示出了捕捉與氣泡階段的位置,再來來看看測試例子:

<style>
  .container {
    width: 500px;
    height: 100px;
    background: #aaaadd;
  }

  .text {
    background: #cccccc;
  }
</style>

<div class="container">
  container area
  <p class="text">Lorem ipsum dolor sit amet.</p>
</div>
const container = document.querySelector('.container');
const text = document.querySelector('.text');

container.addEventListener('click', test, true);
function test(e) {
  console.log('點擊到的元素為: container');
}

text.addEventListener('click', test2, true);
function test2(e) {
  console.log('點擊到的元素為: text');
}

HTML 畫面如下:

Day22-2

  1. containertext 皆設定參數為false,當點擊 text 時:
    搭配剛剛的 DOM 結構圖驗證,表示兩者皆於氣泡階段執行,在氣泡階段的執行順序為先 textcontainer,所以會得到如圖的結果。

Day22-3

  1. containertext 皆設定參數為true,當點擊 text 時:
    表示兩者皆於捕捉階段執行,在捕捉階段的執行順序為先 containertext,所以會得到如圖的結果。

Day22-4

  1. container 參數為truetext 參數為false,當點擊 text 時:
    表示container 在捕捉階段執行而 text 在氣泡階段執行。所以執行順序為先 containertext,所以會得到如圖的結果。

Day22-4

  1. container 參數為falsetext 參數為true ,當點擊 text 時:
    表示container 在氣泡階段執行而 text 在捕捉階段執行。所以執行順序為先 textcontainer,所以會得到如圖的結果。

Day22-3

e.stopPropagation

因為傳遞機制,所以在點擊 text 元素時,也會因此讓 container 也在這個過程中觸發行為。

但如果不想要這樣子的話,就必須使用 e.stopPropagation()

e.stopPropagation() 可以阻止當前事件捕捉與冒泡的傳遞,如此就不會在這個過程中同時也觸發到其他元素。

所以來將測試例子改寫一下:

const container = document.querySelector('.container');
const text = document.querySelector('.text');

container.addEventListener('click', test, true);
function test(e) {
  console.log('點擊到的元素為: container');
}

text.addEventListener('click', test2, true);
function test2(e) {
  e.stopPropagation();
  console.log('點擊到的元素為: text');
}

當點擊 text 元素時,因為 e.stopPropagation() 會終止事件傳遞,所以可以得到如圖結果。

Day22-5

e.preventDefault

最後是如何取消元素自有的預設行為,舉例來說,當點擊 html 的 <a> 標籤時,會直接導向設定的連結。

但有時候我們會希望先經過一些處理後才導向某個網址,這個時候就需要用到 e.preventDefault() 了。

透過 e.preventDefault 可以將 HTML 的 <a> 標籤點擊後自動導向的默認行為取消,來看看測試例子

<a href ="http://www.google.com" class="link">This is a link</a>
const link  = document.querySelector('.link');
link.addEventListener('click',test);

function test(e){
  e.preventDefault();
  console.log(e);
}

可以嘗試將 e.preventDefault() 註解並看看差異性。

今天就到這裡囉~

明天見~


上一篇
透過 JavaScript 動態建立 HTML 元素的幾種方式
下一篇
透過 JavaScript 動態修改CSS 樣式、屬性
系列文
JavaScript 試煉之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言