如何删除元素中的所有侦听器?

IT技术 javascript dom-events addeventlistener
2021-01-28 16:51:27

我有一个按钮,我添加了一些eventlistners

document.getElementById("btn").addEventListener("click", funcA, false);
document.getElementById("btn").addEventListener("click", funcB, false);
document.getElementById("btn").addEventListener("click", funcC, false);
document.getElementById("btn").addEventListener("blur" , funcD, false);
document.getElementById("btn").addEventListener("focus", funcE, false);

<button id="btn">button</button>

我可以通过以下方式删除它们:

document.getElementById("btn").removeEventListener("click",funcA);

如果我想一次删除所有侦听器,或者我没有函数引用 ( funcA) 怎么办?有没有办法做到这一点,或者我必须一个一个地删除它们?

3个回答

我认为最快的方法是克隆节点,这将删除所有事件侦听器:

var old_element = document.getElementById("btn");
var new_element = old_element.cloneNode(true);
old_element.parentNode.replaceChild(new_element, old_element);

请小心,因为这也将清除相关节点的所有子元素上的事件侦听器,因此如果您想保留它,则必须一次显式地删除一个侦听器。

@BenD 有趣的是,有 3 票反对,但没有其他答案……这是那些反对者的一个非常弱的表演!
2021-03-12 16:51:27
@Saxoier 克隆节点肯定比删除侦听器要慢,但在大多数功能场景中,速度差异将无法辨别(除非您一次性对大量页面节点执行此操作)。至于内存泄漏,这将取决于浏览器......所有现代浏览器都应该很好地处理垃圾收集,不会遇到问题(尽管如果节点包含嵌入对象,我可以想象可能发生这种情况的场景)。您是否考虑过特定​​记录的内存泄漏?
2021-03-14 16:51:27
对于那些讨厌神秘布尔参数的人,cloneNode(true) 意味着克隆节点,包括子节点。文档:developer.mozilla.org/en-US/docs/Web/API/Node.cloneNode
2021-04-03 16:51:27
@Saxoier,感谢您的提醒,但我在此页面上进行了测试body,效果很好。也许我使用的是快速浏览器(谷歌浏览器)。
2021-04-08 16:51:27
@Derek:克隆一个节点和整个子树是一个坏主意。这是很多比移除所有较慢EventListener从与节点s node.removeEventListener此外,您将获得内存泄漏(节点 + 子树),当然所有EventListeners 都从子树中删除。如果你使用你的功能,document.body你会炸毁一切。
2021-04-11 16:51:27

如果您使用 jquery 事件,这可以在一行中完成:

对于 jQuery 事件 ( .on()):

$("#myEl").off()

对于原生 javascript 事件 ( .addEventListener()):

$('#myEl').replaceWith($('#myEl').clone());

下面是一个例子:

http://jsfiddle.net/LkfLezgd/3/

不知道为什么会这样unbind并且off不起作用。但是$('#myEl').replaceWith($('#myEl').clone());效果很好!
2021-03-17 16:51:27
看起来这只会删除使用 jQuery 创建的事件,因此不是一个完整的解决方案。
2021-03-19 16:51:27
是否删除off()unbind()仅删除通过 jQuery 附加的那些侦听器?
2021-03-21 16:51:27
这太长了,而在 jQuery 中,您应该这样做$("#myEl").unbind();.off()(1.7+) 删除所有侦听器。
2021-04-04 16:51:27
@davide @Duke确实off()unbind()不会与本地JavaScript注册的监听工作addEventListener,按照jQuery的文档。
2021-04-06 16:51:27

这是一个同样基于 的函数cloneNode,但可以选择仅克隆父节点并移动所有子节点(以保留其事件侦听器):

function recreateNode(el, withChildren) {
  if (withChildren) {
    el.parentNode.replaceChild(el.cloneNode(true), el);
  }
  else {
    var newEl = el.cloneNode(false);
    while (el.hasChildNodes()) newEl.appendChild(el.firstChild);
    el.parentNode.replaceChild(newEl, el);
  }
}

删除一个元素上的事件侦听器:

recreateNode(document.getElementById("btn"));

删除元素及其所有子元素上的事件侦听器:

recreateNode(document.getElementById("list"), true);

如果您需要保留对象本身并因此不能使用cloneNode,那么您必须自己包装addEventListener函数并跟踪侦听器列表,就像在这个答案中一样

@Max:我很欣赏你的编辑建议,但我相信将这段代码改造成 ES2015 在这种情况下是不合理的,那时代码不会得到广泛支持。
2021-03-22 16:51:27
删除你可以使用的所有孩子听: element.innerHTML += '';
2021-03-30 16:51:27
@NazarVynnytskyi 确实,这是一个快速而肮脏但有效的解决方案!
2021-04-10 16:51:27