如何移除事件监听器 - chuckQu
source link: https://www.cnblogs.com/chuckQu/p/17220905.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
如何移除事件监听器
在运行时清理你的代码是构建高效、可预测的应用程序,没有商量余地的部分。在JavaScript中,实现这一目标的方法之一是很好地管理事件监听器,尤其是当不再需要时移除它们。
有好几种方法可以做到这件事情,每种都有自己的一套权衡方法,使其在某些情况下更合适。我们将介绍几种最常用的策略,以及当你试图决定哪种方法最适合于任何特定时间的工作时,需要考虑的一些问题。
我们将对下面的设置进行修补--一个带有单击事件监听器的按钮:
<button id="button">Do Something</button>
<script>
document.getElementById('button').addEventListener('click', () => {
console.log('clicked!');
});
</script>
使用getEventListeners()
函数,你会看到只有一个监听器连接到该元素:
如果你需要移除该监听器,你可以用以下几个方法。
使用.removeEventListener()
这可能是最显而易见的,但也是最有可能威胁到你心智的一个。.removeEventListener()
方法接收三个参数:待移除监听器的类型,监听器的回调函数,以及可选对象。
但这里有一个(潜在的)棘手的部分:这些确切的参数必须与设置监听器时使用的参数完全一致,包括内存中回调的相同引用。否则,.removeEventListener()
啥也不做。
考虑到这一点,下面的示例将是完全无效的:
document.getElementById('button').addEventListener('click', () => {
console.log('clicked!');
});
document.getElementById('button').removeEventListener('click', () => {
console.log('clicked!');
});
尽管回调函数看起来一样,但它们不是相同的引用。解决方案是将回调函数设置为一个变量,并在.addEventListener()
和.removeEventListener()
中引用它。
const myCallback = () => {
console.log('clicked!');
};
document.getElementById('button').addEventListener('click', myCallback);
document.getElementById('button').removeEventListener('click', myCallback);
或者,对于特定的用例,你也可以通过在函数本身中引用一个伪匿名函数来移除监听器:
document
.getElementById('button')
.addEventListener('click', function myCallback() {
console.log('clicked!');
this.removeEventListener('click', myCallback);
});
尽管有其特殊性,.removeEventListener()
的优势在于其目的非常明确。当你通读完代码时,对它的作用没有任何疑问。
使用.addEventListener()的once选项
如果.addEventListener()
是为了一次性使用,.addEventListener()
方法自带一个工具可以帮助自己清理:once
选项。这和它听起来一样简单。如果设置为true
,监听器会在第一次被调用后自动移除它自己:
const button = document.getElementById('button');
button.addEventListener('click', () => {
console.log('clicked!');
}, { once: true });
// 'clicked!'
button.click();
// No more listeners!
getEventListeners(button) // {}
假设它符合你的使用情况,如果你热衷于使用匿名函数,这种方法可能是合适的,因为你的监听器只需要被调用一次。
克隆&替换节点
有时,你不知道某个节点上所有活跃的监听器,但你知道你想要摧毁它们。在这种情况下,克隆整个节点并使用克隆的替换该节点是可行的。使用.cloneNode()
方法,通过.addEventListener()
附加的监听器都不会被带过去,给它一个干净的环境。
让我们回到客户端JavaScript的石器时代,你会看到这是由查询到父节点,然后用一个克隆节点替换一个特定的子节点完成的:
button.parentNode.replaceChild(button.cloneNode(true), button);
但在现代浏览器中,可以使用.replaceWith()
进行简化:
button.replaceWith(button.cloneNode(true));
有一件事可能会让你感到困惑,那就是内部监听器会被保留下来,这意味着一个带有onclick
属性的按钮仍然会按照定义触发:
<button id="button" onclick="console.log('clicked!')">
Do Something
</button>
总之,如果你需要用蛮力不分青红皂白地删除任何种类的监听器,这是一个值得一试的选择。然而,在缺点方面,就是它的目的不太明显。有人会说它是一个hack手段。
使用AbortController()
该方法对我来说是新的。我是在看到Caleb Porzio的这条推文时才知道的。如果你和我一样,你可能只听说过AbortController
是用来取消fetch()
请求的。但显然,它比这更灵活。
最近,.addEventListener()
可以设置一个signal
,用于终止/移除一个监听器。当相应的控制器调用.abort()
时,该信号将触发监听器被删除:
const button = document.getElementById('button');
const controller = new AbortController();
const { signal } = controller;
button.addEventListener('click', () => console.log('clicked!'), { signal });
// Remove the listener!
controller.abort();
这样做最明显的好处可能是符合人体工程学。它(在我看来)是一种更清晰的移除监听器的方式,而不用处理.removeEventListener()
的潜在麻烦。但也有一个更具战术性的优势:你可以使用一个信号来一次性移除多个任何类型的监听器。而且使用匿名函数也是完全可以的:
const button = document.getElementById('button');
const controller = new AbortController();
const { signal } = controller;
button.addEventListener('click', () => console.log('clicked!'), { signal });
window.addEventListener('resize', () => console.log('resized!'), { signal });
document.addEventListener('keyup', () => console.log('pressed!'), { signal });
// Remove all listeners at once:
controller.abort();
唯一让人犹豫不决的原因是浏览器支持。这是一个相对较新的功能,自2021年(v90)以来,Chrome浏览器才全面支持。因此,如果你需要支持超过有几年历史的浏览器版本,请记住这一点。
应该使用哪个
跟其他事情一样,这取决于实际使用场景:
- 使用
.removeEventListener()
:如果回调函数被赋值给一个变量,并且在监听器被添加的地方很容易找到时可以使用该方式。 - 使用
once
选项:如果你只需要触发一次回调时,可以使用该方式。 - 使用克隆和替换方法:如果你需要一股脑销毁多个监听器时,可以使用该方式。
- 使用
AbortController()
:如果你有一系列的监听器想一次性地删除,或者你只是喜欢这种语法时可以使用该方式。
以上就是本文的全部内容,如果对你有所帮助,欢迎点赞、收藏、转发~
Recommend
-
65
前言 在实际开发过程中,经常会碰见一些比如系统启动初始化信息、统计在线人数、在线用户数、过滤敏高词汇、访问权限控制(URL级别)等业务需求。这些对于业务来说一般上是无关的,业务方是无需关系的,业务只需要关系自己内部...
-
30
使用 Web Workers 优化事件监听器 我最近一直在捣鼓 Web Worker API,结果,我真的后悔没有尽早去研究这个功能强大的工具。现代 Web...
-
6
一个完整的Http请求包括客户端(常常为浏览器)请求和服务器响应两大部分,那么你清楚在这个过程中底层都做了哪些事情吗?又如HTTP请求的短连接和长连接底层的区别是什么?再如何基于Netty定制开发符合特定业务场景的HTTP监听器 ...
-
32
过滤器 过滤器简介 过滤器的英文名称为 Filter, 是 Servlet 技术中最实用的技术。如同它的名字一样,过滤器是处于客户端和服务器资源文件之间的一道过滤网,帮助我们过滤掉一些不符合要求的请求,通常用作 S...
-
8
打破国外垄断,开发中国人自己的编程语言(2):使用监听器实现计算器 上一篇:
-
11
Web监听器导图详解 监听器是JAVA Web开发中很重要的内容,其中涉及到的知识,可以参考下面导图: 一、Web监听器 1. 什么是web监听器? web监听器是一种Servlet中的特殊的类,它们能帮助开发者监听web中的特定事...
-
5
本文已收录到《10万字Springboot经典学习笔记》中, 微信搜索: 武哥聊编程 ...
-
8
mini-spring 中文版 About The mini-spring is a simplified version of the Spring framework that will help you qui...
-
5
haorooms前端博客,保持了7年百度首页搜索前端博客第一,最近搜索发现博客排名不见了。并没有做什么网站改版之类的。也没有什么SEO的作弊行为。难道是因为近期网站没有更新吗?好吧,那么最近来频繁更新一波,提升一下...
-
4
Js如何移除事件监听器更新日期: 2023-03-16阅读: 57标签: 事件分享
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK