如何避免重复addEventListener?

避免重复addEventListener的核心就是在添加前通过removeEventListener将已经添加的处理函数进行移除。如下代码为id=btn的元素添加click事件的处理函数clickHandler

const $btn = document.getElementById('btn');
function clickHandler() {
	console.info(`this is in clickHandler`);
}

$btn.removeEventListener('click', clickHandler);
$btn.addEventListener('click', clickHandler);

但是在这里涉及到一个问题,JavaScript中函数是引用类型,因此在进行removeEventListener时,第二个参数需要和addEventListener时的引用相同,否则无法达到移除的效果。如下代码所示:

Html部分代码如下

<body>
<h1 id="btn">click here</h1>

<section>
    <button onclick="addListener()" id="btnForBtn">add handler for click here</button>
</section>

JavaScript代码如下

const $btn = document.getElementById('btn');

let count = 0;

function addListener() {
	function clickHandler() {
	    console.info(`this is in clickHandler but created ${++count} times`);
	}

	$btn.removeEventListener('click', clickHandler);
	$btn.addEventListener('click', clickHandler);
}

效果图,如下:
这里写图片描述

点击add handler to click here按钮为click here按钮添加点击事件,并在添加前进行移除,希望达到唯一处理函数的效果。右侧输出展示的是六次add handler to click here按钮点击,一次click here按钮点击的效果。可以看到,并未达到预期。原因是:每次执行函数addListener都重新创建了clickHandler函数,因此在进行removeEventListener时并未将原有的处理函数进行移除

如果将clickHandler移动到addListener函数之外仅进行一次定义,那么是可以达到唯一添加的效果,但是在有些业务需求中需要进行如此类代码结构的编写方式(如Vue中,在directive的各生命周期中进行事件绑定)。而此时为了达到唯一绑定的效果,其实就是保存clickHandler的唯一引用的问题。如果不能提取到外部作为全局变量,那么换个思路,作为待绑定元素的属性也就可以了,JavaScript代码如下:

const $btn = document.getElementById('btn');

let count = 0;

function addListener() {
	if ($btn.clickHandler) {
		$btn.removeEventListener('click', $btn.clickHandler);
	}

	$btn.clickHandler = () => {
		console.info(`this is in clickHandler but created ${++count} times`);
	};

	$btn.addEventListener('click', $btn.clickHandler);
}

效果图,如下:
这里写图片描述

这里需要注意的是:

  1. 过多的在元素上绑定属性,有可能会造成性能的损耗和增加维护的成本
  2. clickHandler属性的定义应该进行命名空间的限制,以避免发生同名属性覆盖的问题

最后需要提到的是,对同一个元素的同一个事件重复进行处理函数的添加,是只生效一次的,如下代码中:

const $btn = document.getElementById('btn');

const clickHandler = () => {
	console.info('this is handler1')
};

// 多次添加同一个事件处理函数,则不会重复执行
$btn.addEventListener('click', clickHandler);
$btn.addEventListener('click', clickHandler);

在页面中对$btn元素进行点击,clickHandler将只执行一次。

学艺不足,欢迎各位看官纠正指错,祝各位生活愉快,工作顺利~~

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值