关于javascript:如何移除事件监听器

在运行时清理你的代码是构建高效、可预测的应用程序,没有商量余地的局部。在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():如果你有一系列的监听器想一次性地删除,或者你只是喜爱这种语法时能够应用该形式。

以上就是本文的全部内容,如果对你有所帮忙,欢送点赞、珍藏、转发~

【腾讯云】轻量 2核2G4M,首年65元

阿里云限时活动-云数据库 RDS MySQL  1核2G配置 1.88/月 速抢

本文由乐趣区整理发布,转载请注明出处,谢谢。

您可能还喜欢...

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据