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/n/333956.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
HIDXLHIDXL
上一篇 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

发表回复

登录后才能评论