天天看點

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

// 每日前端夜話 第367篇
// 正文共:1500 字
// 預計閱讀時間:6 分鐘
                
addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

為什麼要進行事件委托?

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

為了實作這個小功能,你需要選擇按鈕,然後再用

addEventListener()

方法來附加事件監聽器:

<button id="buttonId">Click mebutton>

<script>document.getElementById('buttonId')
    .addEventListener('click', () => console.log('Clicked!'));script>
                

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

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

<div id="buttons">
  <button class="buttonClass">Click mebutton>
  <button class="buttonClass">Click mebutton>
  
  <button class="buttonClass">Click mebutton>
div>

<script>const buttons = document.getElementsByClassName('buttonClass');for (const button of buttons) {
    button.addEventListener('click', () => console.log('Clicked!'));
  }script>
                

你可以在 Codesandbox 上檢視它是怎樣工作的[1]。

按鈕清單被疊代為

for (const button of buttons)

,并且每個按鈕都被附加了一個新的偵聽器。另外在清單中的按鈕被添加或删除後,你必須還要手動删除或附加事件監聽器。

有沒有更好的方法?

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

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

事件傳播

當你單擊下面 html 中的按鈕時:

<html>
  <body>
    <div id="buttons">
      <button class="buttonClass">Click mebutton>
    div>
  body>
html>
                

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

document

window

對象也會收到。

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

  1. 捕獲階段 —— 從

    window

    document

    和根元素開始,事件向下擴散至目标元素的祖先
  2. 目标階段 —— 事件在使用者單擊的元素上觸發
  3. 冒泡階段——最後,事件冒泡通過目标元素的祖先,一直到根元素

    document

    window

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

JavaScript事件傳播

addEventListener

方法的第三個參數

captureOrOptions

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

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

  • 如果缺少

    captureOrOptions

    參數,或者參數為

    false

    {capture:false}

    ,那麼偵聽器将捕獲**目标(target)和 冒泡階段(bubble phases)**的事件
  • 如果參數是

    true

    {capture:true}

    ,那麼偵聽器将會偵聽**捕獲階段(capture phase)**的事件。

通過下面的代碼,你會偵聽到在

元素上發生的捕獲階段的點選事件:

document.body.addEventListener('click', () => {
  console.log('Body click event in capture phase');
}, true);
                

在這個 Codesandbox 示範[2]中,單擊按鈕時,你可以在控制台中檢視事件的傳播方式。

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

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

3.事件委托

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

<div id="buttons"> 
  <button class="buttonClass">Click mebutton>
  <button class="buttonClass">Click mebutton>
  
  <button class="buttonClass">Click mebutton>
div>

<script>document.getElementById('buttons')
    .addEventListener('click', event => { // Step 2if (event.target.className === 'buttonClass') { // Step 3console.log('Click!');
      }
    });script>
                

打開Codesandbox 示範[3],然後單擊任意按鈕,你會看到

'Click!'

消息被記錄到控制台。

事件委托的思想很簡單。你不需要把委托事件監聽器直接附加到按鈕上,而是可以委托父監聽

。單擊按鈕時,父元素的偵聽器将會捕獲冒泡事件(還記得前面所說事件傳播嗎?)。

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

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

在上面的例子中,

是按鈕的父元素。

步驟 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

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

總結

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

事件從

window

document

、根元素向下傳播,并經過目标元素的祖先(捕獲階段);事件發生在目标(目标階段)上;最後,事件在目标祖先之間冒出氣泡,直到根元素

document

window

(冒泡階段)。

該機制稱為事件傳播。

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

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

确定要監視事件的元素的父級元素把将事件偵聽器附加到父元素用

event.target

選擇目标元素作者:Dmitri Pavlutin 翻譯:瘋狂的技術宅 原文:https://dmitripavlutin.com/javascript-event-delegation/

Reference

[1]

在 Codesandbox 上檢視它是怎樣工作的: https://codesandbox.io/s/infallible-archimedes-6feob?file=/index.html

[2]

Codesandbox 示範: https://codesandbox.io/s/event-propagation-example-71yvl?file=/src/index.js

[3]

Codesandbox 示範: https://codesandbox.io/s/event-delegation-example-6y6gc?file=/index.html

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

前端面試神器助你一臂之力

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托
addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托
addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

精彩文章回顧,點選直達

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

轉了嗎

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

贊了嗎

addeventlistener事件第三個參數_淺析 JavaScript 中的事件委托

在看嗎

繼續閱讀