首頁 > web前端 > js教程 > 深入淺析JS中的事件委託

深入淺析JS中的事件委託

青灯夜游
發布: 2021-02-01 17:50:41
轉載
1832 人瀏覽過

深入淺析JS中的事件委託

為什麼要進行事件委託?

先實作一個小功能:在點選 HTML 的按鈕後,把訊息輸出到控制台。

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

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

<script>
  document.getElementById(&#39;buttonId&#39;)
    .addEventListener(&#39;click&#39;, () => console.log(&#39;Clicked!&#39;));
</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(&#39;buttonClass&#39;);
  for (const button of buttons) {
    button.addEventListener(&#39;click&#39;, () => console.log(&#39;Clicked!&#39;));
  }
</script>
登入後複製

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

按鈕清單被迭代為 for (const button of buttons) ,並且每個按鈕都被附加了一個新的偵聽器。另外在清單中的按鈕被新增或刪除後,你必須也要手動刪除或附加事件監聽器。

有沒有更好的方法?

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

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

事件傳播

當你點擊下面 html 中的按鈕:

<html>
  <body>
    <div id="buttons">
      <button class="buttonClass">Click me</button>
    </div>
  </body>
</html>
登入後複製

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

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

  • 擷取階段 —— 從windowdocument 和根元素開始,事件向下擴散至目標元素的祖先

  • 目標階段 —— 事件在使用者點擊的元素上觸發

  • 冒泡階段-最後,事件冒泡通過目標元素的祖先,一直到根元素documentwindow

深入淺析JS中的事件委託

深入淺析JS中的事件委託

addEventListener 方法的第三個參數captureOrOptions# :

element.addEventListener(eventType, handler[, captureOrOptions]);
登入後複製

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

  • 如果缺少captureOrOptions 參數,或參數為false{capture:false},那麼偵聽器將會擷取目標(target)和冒泡階段(bubble phases)的事件
  • 如果參數是true{capture:true},那麼偵聽器將會偵聽捕獲階段(capture phase)的事件。

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

document.body.addEventListener(&#39;click&#39;, () => {
  console.log(&#39;Body click event in capture phase&#39;);
}, true);
登入後複製

在這個Codesandbox 示範中,當點擊按鈕時,你可以在控制台中查看事件的傳播方式。

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

這個演算法很簡單:把事件偵聽器附加到按鈕的父級,並在點擊按鈕時捕捉冒泡事件。這就是事件委託的工作方式。

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(&#39;buttons&#39;)
    .addEventListener(&#39;click&#39;, event => { // Step 2
      if (event.target.className === &#39;buttonClass&#39;) { // Step 3
        console.log(&#39;Click!&#39;);
      }
    });
</script>
登入後複製

開啟Codesandbox 演示,然後點擊任一按鈕,你會看到 'Click!' 訊息被記錄到控制台。

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

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

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

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

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

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

步骤3:用 event.target 选择目标元素

单击按钮时,将会用event 对象参数调用处理函数。属性 event.target 访问在其上调度了事件的元素,在例子中是一个按钮:

// ...
.addEventListener(&#39;click&#39;, event => {
    if (event.target.className === &#39;buttonClass&#39;) {      
        console.log(&#39;Click!&#39;);
    }
});
登入後複製

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

现在,你可以看到事件委托模式的好处:事件委托仅需要一个事件侦听器,而不必像本文最初那样将侦听器附加到每一个按钮上。

总结

当发生点击事件(或传播的任何其他事件)时:

  • 事件从 windowdocument、根元素向下传播,并经过目标元素的祖先(捕获阶段);
  • 事件发生在目标(目标阶段)上;
  • 最后,事件在目标祖先之间冒出气泡,直到根元素 documentwindow(冒泡阶段)。

该机制称为事件传播

事件委托是一种有用的模式,因为你可以只需要用一个事件处理程序就能侦听多个元素上的事件。

使用事件委托需要三个步骤:

  • 确定要监视事件的元素的父级元素

  • 把将事件侦听器附加到父元素

  • event.target 选择目标元素

更多计算机编程相关知识,请访问:编程视频!!

以上是深入淺析JS中的事件委託的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:51cto.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門推薦
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板