淺析 JavaScript 中的事件委托說明

2020-09-19 18:21:21 編輯:小船網絡 來源:本站原創

1、為什么要進行事件委托?

首先實現一個小功能:在單擊 HTML 的按鈕后,把消息輸出到控制臺。

為了實現這個小功能,你需要選擇按鈕,然后再用 addEventListener() 方法來附加事件監聽器:

<button id="buttonId">Click me</button>

<script>

  document.getElementById('buttonId')

    .addEventListener('click', () => console.log('Clicked!'));

</script>

以上就是偵聽單個元素(尤其是按鈕)上事件的方式。

如果需要監聽多個按鈕上的事件呢?下面是一種可能的實現:

<div id="buttons">

  <button class="buttonClass">Click me</button>

  <button class="buttonClass">Click me</button>

  <!-- buttons... -->

  <button class="buttonClass">Click me</button>

</div>

<script>

  const buttons = document.getElementsByClassName('buttonClass');

  for (const button of buttons) {

    button.addEventListener('click', () => console.log('Clicked!'));

  }

</script>

按鈕列表被迭代為 for (const button of buttons) ,并且每個按鈕都被附加了一個新的偵聽器。另外在列表中的按鈕被添加或刪除后,你必須還要手動刪除或附加事件監聽器。

有沒有更好的方法?

幸運的是,如果我們使用“事件委托”模式的話,偵聽多個元素上的事件只需要一個事件偵聽器。

事件委托使用事件傳播機制的細節。想要要了解事件委托的工作原理,應該先了解什么是事件傳播。

 

2、事件傳播

點擊事件會觸發多少個元素?毫無疑問,按鈕本身會收到單擊事件。而且所有按鈕的祖先,甚至包括 document 和 window 對象也會收到。

點擊事件的傳播分三個階段:

1.捕獲階段 —— 從window,document 和根元素開始,事件向下擴散至目標元素的祖先

2.目標階段 —— 事件在用戶單擊的元素上觸發

3.冒泡階段——最后,事件冒泡通過目標元素的祖先,一直到根元素 document 和 window。

addEventListener 方法的第三個參數 captureOrOptions:

element.addEventListener(eventType, handler[, captureOrOptions]);

使你可以捕獲來自不同階段的事件。

如果缺少 captureOrOptions 參數,或者參數為 false 或 {capture:false},那么偵聽器將捕獲目標(target)和 冒泡階段(bubble phases)的事件

如果參數是 true 或 {capture:true},那么偵聽器將會偵聽捕獲階段(capture phase)的事件。

通過下面的代碼,你會偵聽到在 <body> 元素上發生的捕獲階段的點擊事件:

document.body.addEventListener('click', () => {

  console.log('Body click event in capture phase');

}, true);

那么事件傳播是怎樣幫助捕獲多個按鈕事件的呢?

該算法很簡單:把事件偵聽器附加到按鈕的父級,并在單擊按鈕時捕獲冒泡事件。這就是事件委托的工作方式。

 

3、事件委托

讓我們用事件委托來捕獲多個按鈕上的點擊:

<div id="buttons"> <!-- Step 1 -->

  <button class="buttonClass">Click me</button>

  <button class="buttonClass">Click me</button>

  <!-- buttons... -->

  <button class="buttonClass">Click me</button>

</div>

<script>

  document.getElementById('buttons')

    .addEventListener('click', event => { // Step 2

      if (event.target.className === 'buttonClass') { // Step 3

        console.log('Click!');

      }

    });

</script>

事件委托的思想很簡單。你不需要把委托事件監聽器直接附加到按鈕上,而是可以委托父監聽 <div id="buttons">。單擊按鈕時,父元素的偵聽器將會捕獲冒泡事件(還記得前面所說事件傳播嗎?)。

使用事件委托需要3個步驟:

步驟1:確定要監視事件的元素的父級元素

在上面的例子中, <div id="buttons"> 是按鈕的父元素。

步驟2:把事件偵聽器附加到父元素

document.getElementById('buttons') .addEventListener('click', handler) 將事件偵聽器附加到按鈕的父元素。該事件偵聽器也會對按鈕單擊做出反應,因為按鈕單擊事件冒泡通過祖先元素(由于事件傳播)。

步驟3:用 event.target 選擇目標元素

單擊按鈕時,將會用event 對象參數調用處理函數。屬性 event.target 訪問在其上調度了事件的元素,在例子中是一個按鈕:

// ...

.addEventListener('click', event => {

    if (event.target.className === 'buttonClass') {      

        console.log('Click!');

    }

});

順便說明一下,event.currentTarget 指向事件偵聽器直接附加到的元素。在例子中,event.currentTarget 是 <div id="buttons">。

現在,你可以看到事件委托模式的好處:事件委托僅需要一個事件偵聽器,而不必像本文最初那樣將偵聽器附加到每一個按鈕上。

總結

當發生點擊事件(或傳播的任何其他事件)時:

事件從 window、document、根元素向下傳播,并經過目標元素的祖先(捕獲階段);

事件發生在目標(目標階段)上;

最后,事件在目標祖先之間冒出氣泡,直到根元素 document 和 window(冒泡階段)。

該機制稱為事件傳播。

事件委托是一種有用的模式,因為你可以只需要用一個事件處理程序就能偵聽多個元素上的事件。

使用事件委托需要三個步驟:

1.確定要監視事件的元素的父級元素

2.把將事件偵聽器附加到父元素

3.用 event.target 選擇目標元素

本站文章均為小船網站建設摘自權威資料,書籍,或網絡原創文章,如有版權糾紛或者違規問題,請即刻聯系我們刪除,我們歡迎您分享,引用和轉載,我們謝絕直接復制和抄襲!感謝...
我們猜你喜歡
伊人久久大线蕉av色首页