有没有一种普通函数可以删除所有事件监听器,而不影响后代节点?

4

这个问题基本上是我所问的,但有不删除后代节点事件的限制。

这个fiddle中,我试图通过将它从DOM中删除并重新放置来移除附加的监听器。

function removeListeners(el) {
    var par = el.parentNode;
    var place = el.nextSibling;
    par.removeChild(el);
    par.insertBefore(el, place);
}

很遗憾这个方法没有起作用,但你仍然可以点击来改变背景(这其实很好,我之前不知道可以在元素不在DOM中的情况下附加事件)。

鉴于这一发现,我尝试了this

function removeListeners(el) {
    var par = el.parentNode;
    var clone = el.cloneNode(false);
    par.replaceChild(clone, el);

    for (var index = 0; index < el.childNodes.length; ++index)
        clone.appendChild(el.childNodes[index]);
}

这里尝试进行浅拷贝,然后将所有子项复制回来,但并没有复制所有的子元素。

前面提到的问题的答案说:“[如果您希望子项保留其侦听器],则必须显式地逐个删除侦听器。”我不知道您将如何实现。
我猜他的意思是获取事件类型列表,然后逐个删除每个事件类型的侦听器(就像 jQuery 一样)。这不仅对于自定义事件是不可能的,而且原生 JS 没有这样的功能(必须指定要删除的函数)。

2个回答

5
Node.childNodes不是一个数组,而是一个NodeList(请参见MDN上的NodeList)。当DOM更新时,它会动态更新。
在您的情况下,您正在将元素移动到新的parentNode中并清空childNodes集合。
您可以使用Array.prototype.slice将childNodes复制到数组中,或者反向迭代。
function removeListeners(el) {
    var par = el.parentNode;
    var clone = el.cloneNode(false);
    par.replaceChild(clone, el);

    for (var index = el.childNodes.length - 1; index >= 0; --index)
        clone.insertBefore(el.childNodes[index], clone.childNodes[0]);
}

那是有道理的。如果我倒序迭代,它会起作用吗?我试过了,你是对的,已点赞。 - Hashbrown
你本可以反向迭代,但是在将元素按正确顺序插入新克隆中时会很麻烦。像这里所做的那样将childNodes复制到数组中更容易理解。 - Julian Descottes
哦,我所说的 bug 是指我的代码中的问题(显然不是浏览器的问题)。在这种情况下,它肯定是一个 bug。 - Hashbrown
好的,我的错误。我已经将你的实现添加到我的答案中了。 - Julian Descottes

0

我设法让我的第二次尝试工作了。
然后,由于@JulianDescottes注意到我的疏忽,我制作了这个更简洁的版本。

这里是工作代码。

function removeListeners(el) {
    //only replace the ancestor element
    var clone = el.cloneNode(false);

    //copy children backwards because of the removal
    for (var index = el.childNodes.length - 1; index >= 0; --index)
        clone.insertBefore(el.childNodes[index], clone.firstChild);

    //insert back into DOM
    el.parentNode.replaceChild(clone, el);
}

我希望有更本地化的解决方案,我担心使用这种方法会有意想不到的后果,我不喜欢从DOM中删除东西,并期望它们在之后能正常工作。
至少比当前的建议更有效率,如果有人提出更好的解决方案,我将感激不尽并接受你的答案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接