删除已经存在的事件监听器
Remove already existing event listener
我正在尝试从对象中删除一个已经存在的事件侦听器。我尝试了几种方法(使用 jQuery .off()
、.unbind(),
标准 removeEventsListeners()
),但如文档中所述,它们只能删除以前添加的方法?
使用 Chrome 调试器,我可以查看并删除指定的事件侦听器,
此外,当尝试通过 jQuery _data()
函数列出事件侦听器时,它不会列出事件。几个小时以来一直在寻找答案。
有人可以帮忙吗?任何解决方法?
编辑: 我必须保留一些,所以无法克隆。
如果事件处理程序是使用 addEventListener
添加的,除非您有对添加的处理程序函数的引用,否则无法删除它。我认为一定是这样,因为如果它与 jQuery 的 on
(or various shortcuts for it), off
挂钩就可以,而你说它不起作用。
解决此问题的一种方法是 用克隆元素替换 元素。当您使用 DOM 的 cloneNode
, you don't copy its event handlers. So if you start out with element
, then you can clone it, use insertBefore
to insert the clone, then use removeChild
克隆元素以删除原始元素时:
var newElement = element.cloneNode(true); // true = deep
element.parentNode.insertBefore(newElement, element);
element.parentNode.removeChild(element);
当然,这确实是一种解决方法。正确的做法是一开始就不要设置处理程序,或者保留对它的引用(如果您以后需要能够将其删除)。
在评论中你说你不能那样做,并问:
Is there a way to add a new event listener that blocks the already existing one?
只有你能到达先,否则不行,你不能。
您不能添加阻止现有处理程序的新处理程序(不是以跨浏览器的标准方式),但如果您可以在添加另一个处理程序之前添加您的处理程序,则可以通过使用来阻止它被调用stopImmediatePropagation
:
// Your handler
document.getElementById("target").addEventListener("click", function(e) {
console.log("Your handler");
e.stopImmediatePropagation();
e.stopPropagation();
});
// The one that you're trying to prevent
document.getElementById("target").addEventListener("click", function(e) {
console.log("Handler you're trying to prevent");
});
<div id="target">Click me</div>
因此,例如,如果在 window
load
事件中添加了另一个处理程序,或者 jQuery ready
处理程序,您也许可以获得您的处理程序首先,将您的代码放在相关元素之后的 script
标记中。
一个非常简单的方法是使用 .innerHTML 不向父元素附加任何内容。请注意,这会破坏作为父元素后代的所有事件侦听器。下面是一个例子(点击2销毁附加到1的事件监听器):
const d1 = document.querySelector('#d1');
d1.addEventListener('click', () => console.log(123));
const d2 = document.querySelector('#d2');
d2.addEventListener('click', () => d1.parentNode.innerHTML += '');
<div><button id="d1">1</button></div>
<div><button id="d2">2</button></div>
我正在尝试从对象中删除一个已经存在的事件侦听器。我尝试了几种方法(使用 jQuery .off()
、.unbind(),
标准 removeEventsListeners()
),但如文档中所述,它们只能删除以前添加的方法?
使用 Chrome 调试器,我可以查看并删除指定的事件侦听器,
此外,当尝试通过 jQuery _data()
函数列出事件侦听器时,它不会列出事件。几个小时以来一直在寻找答案。
有人可以帮忙吗?任何解决方法?
编辑: 我必须保留一些,所以无法克隆。
如果事件处理程序是使用 addEventListener
添加的,除非您有对添加的处理程序函数的引用,否则无法删除它。我认为一定是这样,因为如果它与 jQuery 的 on
(or various shortcuts for it), off
挂钩就可以,而你说它不起作用。
解决此问题的一种方法是 用克隆元素替换 元素。当您使用 DOM 的 cloneNode
, you don't copy its event handlers. So if you start out with element
, then you can clone it, use insertBefore
to insert the clone, then use removeChild
克隆元素以删除原始元素时:
var newElement = element.cloneNode(true); // true = deep
element.parentNode.insertBefore(newElement, element);
element.parentNode.removeChild(element);
当然,这确实是一种解决方法。正确的做法是一开始就不要设置处理程序,或者保留对它的引用(如果您以后需要能够将其删除)。
在评论中你说你不能那样做,并问:
Is there a way to add a new event listener that blocks the already existing one?
只有你能到达先,否则不行,你不能。
您不能添加阻止现有处理程序的新处理程序(不是以跨浏览器的标准方式),但如果您可以在添加另一个处理程序之前添加您的处理程序,则可以通过使用来阻止它被调用stopImmediatePropagation
:
// Your handler
document.getElementById("target").addEventListener("click", function(e) {
console.log("Your handler");
e.stopImmediatePropagation();
e.stopPropagation();
});
// The one that you're trying to prevent
document.getElementById("target").addEventListener("click", function(e) {
console.log("Handler you're trying to prevent");
});
<div id="target">Click me</div>
因此,例如,如果在 window
load
事件中添加了另一个处理程序,或者 jQuery ready
处理程序,您也许可以获得您的处理程序首先,将您的代码放在相关元素之后的 script
标记中。
一个非常简单的方法是使用 .innerHTML 不向父元素附加任何内容。请注意,这会破坏作为父元素后代的所有事件侦听器。下面是一个例子(点击2销毁附加到1的事件监听器):
const d1 = document.querySelector('#d1');
d1.addEventListener('click', () => console.log(123));
const d2 = document.querySelector('#d2');
d2.addEventListener('click', () => d1.parentNode.innerHTML += '');
<div><button id="d1">1</button></div>
<div><button id="d2">2</button></div>