是否有一个vanilla函数来删除所有事件侦听器而不影响后代节点?

Has*_*own 4 javascript javascript-events

这个问题基本上就是我要问的问题,但是没有为后代节点删除事件的限制.

这个小提琴中,我尝试通过从DOM中删除它并将其放回来删除附加的侦听器.

function removeListeners(el) {
    var par = el.parentNode;
    var place = el.nextSibling;
    par.removeChild(el);
    par.insertBefore(el, place);
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这不起作用,你仍然可以点击以获得改变的背景(这实际上很好,我从来不知道你可以附加没有元素在DOM中的事件).

鉴于这一发现我试过这个

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]);
}
Run Code Online (Sandbox Code Playgroud)

尝试做一个浅层克隆,然后将所有后代复制回来,但它不会复制所有孩子.

上述问题的回答说:"[如果你想有孩子们保持他们的听众]你将不得不求助于明确地去除听众一次一个".我不知道你将如何实现这一点.
我认为他的意思是获取事件类型列表并依次删除每个事件的侦听器(如jQuery可以).这不仅对自定义事件不可能,而且vanilla JS 没有这样的功能(您必须指定要删除的功能).

小智 5

Node.childNodes不是Array,而是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]);
}
Run Code Online (Sandbox Code Playgroud)