溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JS中事件委托的示例分析

發(fā)布時(shí)間:2021-02-23 13:40:02 來源:億速云 閱讀:139 作者:小新 欄目:web開發(fā)

這篇文章主要介紹JS中事件委托的示例分析,文中介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們一定要看完!

為什么要進(jìn)行事件委托?

首先實(shí)現(xiàn)一個(gè)小功能:在單擊 HTML 的按鈕后,把消息輸出到控制臺。

為了實(shí)現(xiàn)這個(gè)小功能,你需要選擇按鈕,然后再用 addEventListener() 方法來附加事件監(jiān)聽器:

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

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

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

如果需要監(jiān)聽多個(gè)按鈕上的事件呢?下面是一種可能的實(shí)現(xiàn):

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

你可以在 Codesandbox 上查看它是怎樣工作的。

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

有沒有更好的方法?

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

事件委托使用事件傳播機(jī)制的細(xì)節(jié)。想要要了解事件委托的工作原理,應(yīng)該先了解什么是事件傳播。

事件傳播

當(dāng)你單擊下面 html 中的按鈕時(shí):

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

點(diǎn)擊事件會觸發(fā)多少個(gè)元素?毫無疑問,按鈕本身會收到單擊事件。而且所有按鈕的祖先,甚至包括 documentwindow 對象也會收到。

點(diǎn)擊事件的傳播分三個(gè)階段:

  • 捕獲階段 —— 從window,document 和根元素開始,事件向下擴(kuò)散至目標(biāo)元素的祖先

  • 目標(biāo)階段 —— 事件在用戶單擊的元素上觸發(fā)

  • 冒泡階段——最后,事件冒泡通過目標(biāo)元素的祖先,一直到根元素 documentwindow

JS中事件委托的示例分析

JS中事件委托的示例分析

addEventListener 方法的第三個(gè)參數(shù) captureOrOptions

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

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

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

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

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

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

在這個(gè) Codesandbox 演示中,單擊按鈕時(shí),你可以在控制臺中查看事件的傳播方式。

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

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

3.事件委托

讓我們用事件委托來捕獲多個(gè)按鈕上的點(diǎn)擊:

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

打開Codesandbox 演示,然后單擊任意按鈕,你會看到  'Click!' 消息被記錄到控制臺。

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

使用事件委托需要3個(gè)步驟:

步驟1:確定要監(jiān)視事件的元素的父級元素

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

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

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

步驟3:用 event.target 選擇目標(biāo)元素

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

// ...
.addEventListener('click', event => {
    if (event.target.className === 'buttonClass') {      
        console.log('Click!');
    }
});

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

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

總結(jié)

當(dāng)發(fā)生點(diǎn)擊事件(或傳播的任何其他事件)時(shí):

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

  • 事件發(fā)生在目標(biāo)(目標(biāo)階段)上;

  • 最后,事件在目標(biāo)祖先之間冒出氣泡,直到根元素 documentwindow(冒泡階段)。

該機(jī)制稱為事件傳播。

事件委托是一種有用的模式,因?yàn)槟憧梢灾恍枰靡粋€(gè)事件處理程序就能偵聽多個(gè)元素上的事件。

使用事件委托需要三個(gè)步驟:

  • 確定要監(jiān)視事件的元素的父級元素

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

  • event.target 選擇目標(biāo)元素

以上是“JS中事件委托的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI