JS addeventlistener第三個參數詳解

一、捕獲與冒泡模式

在討論addEventListener第三個參數之前,先來了解一下事件流,也就是事件的傳播方式。

事件流分為兩種:捕獲模式和冒泡模式。在捕獲模式中,事件從最外層的節點開始傳播,一直傳遞到最底層的節點;而冒泡模式則恰好相反,從最底層的節點開始傳播,逐漸向外傳遞,到最後傳遞到最外層的節點。

瀏覽器對事件流的處理分為三個階段:

1. 捕獲階段
2. 目標階段
3. 冒泡階段

捕獲階段是從document對象到觸發事件的最外層元素,目標階段是事件傳播到目標元素,冒泡階段是從目標元素到最外層元素。

在addEventListener中,第三個參數就是用來指定事件模式的,默認值為false,表示使用冒泡模式。如果將其設置為true,則表示使用捕獲模式。

// 冒泡模式
document.getElementById('example').addEventListener('click', function() {
  console.log('我是來自 example 的點擊事件!');
});

// 捕獲模式
document.getElementById('example').addEventListener('click', function() {
  console.log('我是來自 example 的點擊事件!');
}, true);

二、事件委託

事件委託是指利用事件機制,將一個父元素的事件處理程序註冊到子元素中,使得子元素在觸發事件時,可以執行父元素的事件處理程序。

這種編程方式的好處在於,可以減少事件程序的數量,提高頁面性能,並且可以方便地動態添加或刪除子元素,而不需要重新綁定事件處理程序。

實現事件委託的關鍵在於,可以通過事件傳播機制,將子元素的事件傳遞到父元素上。在這個過程中,可以通過第三個參數來控制事件的傳播方式。

以ul元素為父元素,li元素為子元素為例:

// 普通方式註冊事件處理程序
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
  lis[i].addEventListener('click', function() {
    console.log('我是來自' + this.innerText + '的點擊事件!');
  });
}

// 事件委託方式註冊事件處理程序
document.querySelector('ul').addEventListener('click', function(event) {
  if (event.target.tagName.toLowerCase() === 'li') {
    console.log('我是來自' + event.target.innerText + '的點擊事件!');
  }
});

可以看到,事件委託可以減少事件處理程序的數量,也可以方便地動態添加或刪除子元素。

三、事件綁定與解綁

addEventListener除了可以進行事件註冊外,也可以通過removeEventListener方法來進行解綁。removeEventListener需要傳入相同的事件類型、回調函數以及可選的useCapture參數,才能解綁之前相同的listener。

var triggerBtn = document.getElementById('trigger');

function clickEvent() {
  console.log('按鈕被點擊了!');
}

// 綁定事件處理程序
triggerBtn.addEventListener('click', clickEvent);

// 解綁事件處理程序
triggerBtn.removeEventListener('click', clickEvent);

四、一次性事件綁定

有時候我們需要在某個事件觸發後,執行完事件處理程序後,解除事件綁定。由於removeEventListener需要了解之前綁定的listener函數,所以無法實現一次性解綁。不過可以藉助匿名函數實現一次性事件綁定。

// 綁定事件處理程序
document.getElementById('example').addEventListener('click', function() {
  console.log('我是一次性的事件處理程序!');
  document.getElementById('example').removeEventListener('click', arguments.callee);
});

在回調函數內部使用arguments.callee,指向了該函數本身,從而達到了一次性的效果。

五、多次事件觸發的節流和防抖

事件節流和防抖都是為了解決事件頻繁觸發而導致性能問題的問題,事件節流和防抖的本質是一樣的,都是通過降低事件觸發頻率,從而提升性能。

5.1 節流

事件節流的本質是使用setTimeout,實現「定時觸發」。它的實現方式是,第一次觸發事件立即執行事件處理程序,然後在一定時間內不管事件觸發了多少次,都不再執行事件處理程序,直到時間到了之後,才再次執行事件處理程序。

function throttle(fn, delay) {
  let timer = null;
  return function() {
    let args = arguments;
    let that = this;
    if (!timer) {
      timer = setTimeout(function() {
        fn.apply(that, args);
        timer = null;
      }, delay);
    }
  };
}

// 用法
document.getElementById('example').addEventListener('click', throttle(function() {
  console.log('我是通過節流方式處理的點擊事件!');
}, 1000));

5.2 防抖

事件防抖的本質是使用setTimeout,實現「延遲觸發」。它的實現方式是,事件觸發後,等待一定時間,如果在這段時間內沒有再次觸發事件,就執行事件處理程序,否則,重新開始計時。

function debounce(fn, delay) {
  let timer = null;
  return function() {
    let args = arguments;
    let that = this;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(function() {
      fn.apply(that, args);
      timer = null;
    }, delay);
  };
}

// 用法
document.getElementById('example').addEventListener('click', debounce(function() {
  console.log('我是通過防抖方式處理的點擊事件!');
}, 1000));

六、總結

在日常的開發工作中,我們經常需要為元素添加各種事件處理程序,而利用addEventListener提供的第三個參數,可以實現捕獲和冒泡模式的控制、事件委託、事件綁定和解綁、一次性事件綁定、事件節流和防抖等功能,實現更靈活、高效的事件管理。

原創文章,作者:HIDXL,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/333956.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
HIDXL的頭像HIDXL
上一篇 2025-02-05 13:04
下一篇 2025-02-05 13:04

相關推薦

  • JS Proxy(array)用法介紹

    JS Proxy(array)可以說是ES6中非常重要的一個特性,它可以代理一個數組,監聽數據變化並進行攔截、處理。在實際開發中,使用Proxy(array)可以方便地實現數據的監…

    編程 2025-04-29
  • 三星內存條參數用法介紹

    本文將詳細解釋三星內存條上面的各種參數,讓你更好地了解內存條並選擇適合自己的一款。 一、容量大小 容量大小是內存條最基本的參數,一般以GB為單位表示,常見的有2GB、4GB、8GB…

    編程 2025-04-29
  • Python3定義函數參數類型

    Python是一門動態類型語言,不需要在定義變數時顯示的指定變數類型,但是Python3中提供了函數參數類型的聲明功能,在函數定義時明確定義參數類型。在函數的形參後面加上冒號(:)…

    編程 2025-04-29
  • Python input參數變數用法介紹

    本文將從多個方面對Python input括弧里參數變數進行闡述與詳解,並提供相應的代碼示例。 一、基本介紹 Python input()函數用於獲取用戶輸入。當程序運行到inpu…

    編程 2025-04-29
  • Spring Boot中發GET請求參數的處理

    本文將詳細介紹如何在Spring Boot中處理GET請求參數,並給出完整的代碼示例。 一、Spring Boot的GET請求參數基礎 在Spring Boot中,處理GET請求參…

    編程 2025-04-29
  • Hibernate日誌列印sql參數

    本文將從多個方面介紹如何在Hibernate中列印SQL參數。Hibernate作為一種ORM框架,可以通過列印SQL參數方便開發者調試和優化Hibernate應用。 一、通過配置…

    編程 2025-04-29
  • Python Class括弧中的參數用法介紹

    本文將對Python中類的括弧中的參數進行詳細解析,以幫助初學者熟悉和掌握類的創建以及參數設置。 一、Class的基本定義 在Python中,通過使用關鍵字class來定義類。類包…

    編程 2025-04-29
  • Python函數名稱相同參數不同:多態

    Python是一門面向對象的編程語言,它強烈支持多態性 一、什麼是多態多態是面向對象三大特性中的一種,它指的是:相同的函數名稱可以有不同的實現方式。也就是說,不同的對象調用同名方法…

    編程 2025-04-29
  • 全能編程開發工程師必知——DTD、XML、XSD以及DTD參數實體

    本文將從大體介紹DTD、XML以及XSD三大知識點,同時深入探究DTD參數實體的作用及實際應用場景。 一、DTD介紹 DTD是文檔類型定義(Document Type Defini…

    編程 2025-04-29
  • 解析js base64並轉成unit

    本文將從多個方面詳細介紹js中如何解析base64編碼並轉成unit格式。 一、base64編碼解析 在JavaScript中解析base64編碼可以使用atob()函數,它會將b…

    編程 2025-04-29

發表回復

登錄後才能評論