jQuery - 从DOM中删除元素时的触发事件

sa1*_*125 203 jquery events dom triggers

我试图弄清楚当从页面中删除元素时如何执行一些js代码:

jQuery('#some-element').remove(); // remove some element from the page
/* need to figure out how to independently detect the above happened */
Run Code Online (Sandbox Code Playgroud)

是否有为此量身定制的活动,例如:

jQuery('#some-element').onremoval( function() {
    // do post-mortem stuff here
});
Run Code Online (Sandbox Code Playgroud)

谢谢.

mtk*_*one 194

您可以使用jQuery特殊事件.

简单来说,

建立:

(function($){
  $.event.special.destroyed = {
    remove: function(o) {
      if (o.handler) {
        o.handler()
      }
    }
  }
})(jQuery)
Run Code Online (Sandbox Code Playgroud)

用法:

$('.thing').bind('destroyed', function() {
  // do stuff
})
Run Code Online (Sandbox Code Playgroud)

回答Pierre和DesignerGuy评论的补遗:

要在调用时没有回调$('.thing').off('destroyed'),请将if条件更改为:if (o.handler && o.type !== 'destroyed') { ... }

  • 非常好的解决方案.Ben Alman有关于特殊活动的精彩文章以获取更多信息:http://benalman.com/news/2010/03/jquery-special-events/ (15认同)
  • 到目前为止,+1已经完全错过了这些特殊活动,非常有用!刚刚实现上述内容的一件事是,最好将`o.handler()`更改为`o.handler.apply(this,arguments)`否则事件和数据对象不会通过事件传递监听器. (11认同)
  • 但是,当您删除没有jQuery的元素时,这不起作用. (5认同)
  • 这不起作用a)当元素被分离而不是被删除时或b)当一些旧的非jquery库使用innerHTML来破坏你的元素时(类似于djjeck所说的) (5认同)
  • 当你`$('.thing')时,请注意处理程序被调用.unbind('destroyed')`这真的很烦人(因为unbind意味着我们不希望调用处理程序......) (5认同)
  • ```o.type```似乎每次都返回```'destroyed'```所以```if(o.handler && o.type!=='destroyed')```不是工作.调用```.off```时还有其他任何阻止回调的方法吗?对于从DOM中移除而来的```o```对象似乎是完全相同的```..``````http://jsfiddle.net/billjohnston4/wg4ks/3/ (2认同)

Phi*_*nin 114

刚刚检查过,它已经内置在当前版本的JQuery中:

jQuery - v1.9.1

jQuery UI - v1.10.2

$("#myDiv").on("remove", function () {
    alert("Element was removed");
})
Run Code Online (Sandbox Code Playgroud)

重要说明:这是Jquery UI脚本(而不是JQuery)的功能,因此您必须加载两个脚本(jquery和jquery-ui)才能使其正常工作.这是一个例子:http://jsfiddle.net/72RTz/

  • 这部分只是部分有效.如果你对它触发的元素执行`remove`,但如果元素被其他方式破坏,则被覆盖说,它不起作用. (19认同)
  • 这非常有帮助.我了解到,如果您不打算下载整个UI库,则此功能位于jQuery UI的"Widget"组件中. (11认同)
  • 这记录在哪里?我只是查看了jQuery UI小部件文档,但未找到提及此内容.想知道这是否得到官方支持/关于使用它的任何警告...... (5认同)

Ada*_*dam 50

您可以绑定到DOMNodeRemoved事件(DOM Level 3 WC3规范的一部分).

适用于IE9,最新版本的Firefox和Chrome.

例:

$(document).bind("DOMNodeRemoved", function(e)
{
    alert("Removed: " + e.target.nodeName);
});
Run Code Online (Sandbox Code Playgroud)

您还可以在通过绑定插入元素时获得通知 DOMNodeInserted

  • 注意:"将DOM突变侦听器添加到文档会严重降低对该文档的进一步DOM修改的性能(使它们慢1.5到7倍!)." 来自:https://developer.mozilla.org/en/DOM/Mutation_events (13认同)
  • 另见http://stackoverflow.com/questions/3219758/detect-changes-in-the-dom (3认同)

Dav*_*ing 37

没有用于删除元素的内置事件,但您可以通过伪扩展jQuery的默认remove方法创建一个.请注意,必须在实际删除回调之前调用回调以保持引用.

(function() {
    var ev = new $.Event('remove'),
        orig = $.fn.remove;
    $.fn.remove = function() {
        $(this).trigger(ev);
        return orig.apply(this, arguments);
    }
})();

$('#some-element').bind('remove', function() {
    console.log('removed!');
    // do pre-mortem stuff here
    // 'this' is still a reference to the element, before removing it
});

// some other js code here [...]

$('#some-element').remove();
Run Code Online (Sandbox Code Playgroud)

注意:其他海报已经概述了这个答案的一些问题.

  1. 通过html() replace()或其他jQuery方法删除节点时,这将不起作用
  2. 这个事件冒出来了
  3. jQuery UI覆盖也会删除

这个问题最优雅的解决方案似乎是:https://stackoverflow.com/a/10172676/216941

  • 虽然这将检测使用'remove'函数删除的元素,但它将无法检测通过其他方式删除的元素(例如使用jQuery的html,替换等).请查看我的答案以获得更完整的解决方案. (4认同)
  • 这对我来说没有开箱即用 - 我必须从orig.apply返回结果. (3认同)
  • 感谢那!一点点补充:因为remove-event冒泡,你也会在删除子节点时收到它,所以最好用这样的方式编写处理程序:`$('#some-element').bind('remove',function (ev){if(ev.target === this){console.log('removed!');}});` (2认同)

zah*_*zah 32

挂钩.remove()是不是因为有许多方法来删除页面元素(例如,通过使用来处理这一点的最好办法.html(),.replace()等).

为了防止各种内存泄漏危险,内部jQuery将尝试jQuery.cleanData()为每个被删除的元素调用该函数,而不管用于删除它的方法如何.

有关更多详细信息,请参阅此答案:javascript内存泄漏

因此,为了获得最佳结果,您应该挂钩cleanData函数,这正是jquery.event.destroyed插件的作用:

http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js


Str*_*ior 7

对于那些使用jQuery UI的人:

jQuery UI的重写了一些jQuery方法来实现remove这不仅受到处理的事件,当你明确移除给定的元素,而且如果该元素被从DOM任何自洁jQuery方法移除(例如replace,html等) .这基本上允许您将挂钩放入jQuery"清理"与DOM元素关联的事件和数据时触发的相同事件中.

John Resig表示他对未来版本的jQuery核心中实现此事件的想法持开放态度,但我不确定它目前的位置.


Leg*_*nds 6

只需要 jQuery(不需要 jQuery UI)

我已经从 jQuery UI 框架中提取了这个扩展

兼容于:empty()html()remove()

$.cleanData = ( function( orig ) {
    return function( elems ) {
        var events, elem, i;
        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
            try {

                // Only trigger remove when necessary to save time
                events = $._data( elem, "events" );
                if ( events && events.remove ) {
                    $( elem ).triggerHandler( "remove" );
                }

            // Http://bugs.jquery.com/ticket/8235
            } catch ( e ) {}
        }
        orig( elems );
    };
} )( $.cleanData );
Run Code Online (Sandbox Code Playgroud)

使用此解决方案,您还可以取消绑定事件处理程序。

$("YourElemSelector").off("remove");
Run Code Online (Sandbox Code Playgroud)

尝试一下!- 例子

$.cleanData = ( function( orig ) {
    return function( elems ) {
        var events, elem, i;
        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
            try {

                // Only trigger remove when necessary to save time
                events = $._data( elem, "events" );
                if ( events && events.remove ) {
                    $( elem ).triggerHandler( "remove" );
                }

            // Http://bugs.jquery.com/ticket/8235
            } catch ( e ) {}
        }
        orig( elems );
    };
} )( $.cleanData );
Run Code Online (Sandbox Code Playgroud)
$("YourElemSelector").off("remove");
Run Code Online (Sandbox Code Playgroud)

附加演示 - jsBin