如何使用JQuery移除父元素的所有子元素的事件处理程序

16

假设有一个特定的父节点,例如动态创建的模态框div。在向其中添加大量动态html并将这些元素绑定到click、mouseover等事件后,是否有一种方法可以取消与模态div的子元素关联的所有事件绑定?在我的具体示例中,一旦隐藏模态div,就会从dom完全删除它,然后每次需要时重新创建它。

我正在寻找一种不必跟踪所有特定绑定的方式,而只需使用一个调用来说:获取任何具有绑定的子元素并将其“off”。

注意:我可以验证,从dom中删除元素然后重新创建它并不会杀死绑定,因为打开和关闭模态div会导致绑定的事件被触发与创建div的次数相同。我正在使用$(document).on('click', '#abc',function(e) {});来绑定元素。


1
展示一下你是如何绑定的(或者一个绑定的例子)。但是如果你正在使用on(),我建议使用off() - David Thomas
有趣。阅读文档时我注意到,“要从元素中删除所有委托事件而不删除非委托事件,请使用特殊值“**”。”以前不知道这个。 - j08691
如何使用普通的JavaScript实现这个? - Rahul Yadav
4个回答

25
你可以使用unbind()函数,如果你使用了bind()来绑定事件。
  $('#foo').children().unbind();
  $('#foo').children('.class').unbind(); //You can give selector for limiting clildren
如果您使用了on()来绑定事件,请使用off()
 $('#foo').children().off();
 $('#foo').children('class').off();   //You can give selector for limiting clildren

如果要从所有后代元素中移除事件,而不是仅从直接子元素中移除,可以使用后代选择器(“祖先 后代”)

$('#foo *').off(); 

6
children() 只获取直接子元素,而不包括所有后代元素。 - avoliva

21

可以使用 off() 不带参数的方式来解除所有事件绑定。

$('#parent *').off();

如果您真正的意思是子代而不是孩子或后代,请使用#parent > *


5
我也想知道是否需要手动解除已删除元素的每个子元素的绑定。
根据jQuery文档,不需要这样做: jquery docs for remove 如果我们在
内有任意数量的嵌套元素,它们也将被删除。其他jQuery结构,如数据或事件处理程序也会被清除。
由于我很好奇这是否属实,所以我查看了源代码:
function remove( elem, selector, keepData ) {
    var node,
        nodes = selector ? jQuery.filter( selector, elem ) : elem,
        i = 0;

    for ( ; ( node = nodes[ i ] ) != null; i++ ) {
        if ( !keepData && node.nodeType === 1 ) {
            jQuery.cleanData( getAll( node ) );
        }

        if ( node.parentNode ) {
            if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
                setGlobalEval( getAll( node, "script" ) );
            }
            node.parentNode.removeChild( node );
        }
    }

    return elem;
}

如您所见:

jQuery.cleanData( getAll( node ) );

清理已删除元素的所有子元素的所有事件。

因此,最终结论是:如果您使用 $(element).remove().empty(),则已经安全地避免了内存泄漏!


1
有些情况下,您不想直接绑定事件到一个元素。相反,您希望将其绑定到父元素,比如说 "body"。这在您想要全局定义事件监听器但该元素可能尚不存在时是必要的。
$("body").on("mouseenter", ".hover-item", function() {
    // do the thing
}

问题在于如果你尝试在“.hover-item”上运行.off(),它不起作用。或者,如果你尝试在“body”上使用.off(),并使用已经被接受的答案建议的.children(),它也什么都不做。
相反,我认为最佳实践是将事件绑定到特定的类名上,当你想要禁用这些事件时,删除该类名即可:
$(".the-element").removeClass(".hover-item");

现在,该元素将不再启用事件监听器。但是,由于您实际上是在“body”上定义事件监听器的,因此如果您需要在以后的某个时间重新启用悬停效果,您只需使用addClass(“.hover-item”),一切都会正常工作。

现在,这仅适用于对多个项目进行单个动画的情况。悬停事件就是一个很好的例子。例如,您可以将相同的事件应用于所有按钮,而不是为不同的按钮应用不同的悬停事件。但是,如果您只想禁用一个特定按钮的悬停事件,那么这是正确的方法。


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