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

时间:2010-02-04 14:46:04

标签: 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 */

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

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

感谢。

16 个答案:

答案 0 :(得分:194)

您可以使用 jQuery特殊活动

简单来说,

设定:

(function($){
  $.event.special.destroyed = {
    remove: function(o) {
      if (o.handler) {
        o.handler()
      }
    }
  }
})(jQuery)

用法:

$('.thing').bind('destroyed', function() {
  // do stuff
})

回答Pierre和DesignerGuy评论的补遗:

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

答案 1 :(得分:112)

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

jQuery - v1.9.1

jQuery UI - v1.10.2

$("#myDiv").on("remove", function () {
    alert("Element was removed");
})

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

答案 2 :(得分:46)

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

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

示例:

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

通过绑定到DOMNodeInserted

,您也可以在插入元素时收到通知

答案 3 :(得分:37)

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

(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();

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

  1. 当通过html() replace()或其他jQuery方法删除节点时,这不起作用
  2. 此事件冒泡
  3. jQuery UI覆盖也删除
  4. 这个问题最优雅的解决方案似乎是:https://stackoverflow.com/a/10172676/216941

答案 4 :(得分:32)

挂钩.remove()不是处理此问题的最佳方式,因为有很多方法可以从页面中删除元素(例如,使用.html().replace()等)。

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

有关详细信息,请参阅此答案:javascript memory leaks

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

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

答案 5 :(得分:7)

对于那些使用jQuery UI的人:

jQuery UI已经覆盖了一些jQuery方法来实现一个remove事件,该事件不仅在您显式删除给定元素时被处理,而且还会通过任何自清理jQuery从DOM中删除该元素方法(例如replacehtml等)。这基本上允许你在jQuery“清理”与DOM元素相关的事件和数据时触发相同的事件。

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

答案 6 :(得分:4)

我无法让this answer使用解除绑定(尽管更新see here),但能够找到解决方法。答案是创建一个' destroy_proxy'引发“被摧毁”的特殊事件。事件。您将事件监听器放在' destroyed_proxy'然后当你想要解开时,你就解开了被摧毁的'事件:

var count = 1;
(function ($) {
    $.event.special.destroyed_proxy = {
        remove: function (o) {
            $(this).trigger('destroyed');
        }
    }
})(jQuery)

$('.remove').on('click', function () {
    $(this).parent().remove();
});

$('li').on('destroyed_proxy destroyed', function () {
    console.log('Element removed');
    if (count > 2) {
        $('li').off('destroyed');
        console.log('unbinded');
    }
    count++;
});

这是fiddle

答案 7 :(得分:4)

不使用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 );

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

$("YourElemSelector").off("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);


$("#DivToBeRemoved").on("remove", function() {
  console.log("div was removed event fired");
});

$("p").on("remove", function() {
  console.log("p was removed event fired");
});

$("span").on("remove", function() {
  console.log("span was removed event fired");
});

// $("span").off("remove");

$("#DivToBeRemoved").on("click", function() {
  console.log("Div was clicked");
});

function RemoveDiv() {
  //       $("#DivToBeRemoved").parent().html("");    
  $("#DivToBeRemoved").remove();
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>OnRemove event handler attached to elements `div`, `p` and `span`.</h3>
<div class="container">
  <br>
  <button onclick="RemoveDiv();">Click here to remove div below</button>
  <div id="DivToBeRemoved">
    DIV TO BE REMOVED 
    contains 1 p element 
    which in turn contains a span element
    <p>i am p (within div)
      <br><br><span>i am span (within div)</span></p>
  </div>
</div>
&#13;
&#13;
&#13;

其他Demo - jsBin

答案 8 :(得分:3)

我喜欢mtkopone使用jQuery特殊事件的答案,但请注意它不起作用a)当元素被分离而不是删除时b)当一些旧的非jquery库使用innerHTML来破坏你的元素时

答案 9 :(得分:1)

我不确定是否有一个事件句柄,因此您必须保留DOM的副本并在某种轮询循环中与现有DOM进行比较 - 这可能非常讨厌。 Firebug执行此操作 - 如果您检查HTML并运行一些DOM更改,它会在Firebug控制台中突出显示黄色的更改。

或者,你可以创建一个删除功能......

var removeElements = function(selector) {
    var elems = jQuery(selector);

    // Your code to notify the removal of the element here...
    alert(elems.length + " elements removed");

    jQuery(selector).remove();
};

// Sample usage
removeElements("#some-element");
removeElements("p");
removeElements(".myclass");

答案 10 :(得分:1)

这是如何创建jQuery 实时删除侦听器

$(document).on('DOMNodeRemoved', function(e)
{
  var $element = $(e.target).find('.element');
  if ($element.length)
  {
    // do anything with $element
  }
});

或者:

$(document).on('DOMNodeRemoved', function(e)
{
  $(e.target).find('.element').each(function()
  {
    // do anything with $(this)
  }
});

答案 11 :(得分:1)

从jQuery进行的“删除”事件无需添加即可正常工作。及时使用简单的技巧而不是修补jQuery可能更可靠。

只需在要从DOM中删除的元素中修改或添加属性。因此,您可以使用属性“ do_not_count_it”来触发任何更新功能,该功能只会忽略即将销毁的元素。

假设我们有一个表格,其中包含与价格相对应的单元格,而您只需要显示最后一个价格: 这是在删除价格单元时触发的选择器(我们在表格的每一行中都有一个按钮,此处未显示)

$('td[validity="count_it"]').on("remove", function () {
    $(this).attr("validity","do_not_count_it");
    update_prices();
});

这是一个函数,它查找表中的最后一个价格,而不考虑最后一个价格(如果它已被删除)。确实,当触发“删除”事件并调用此函数时,该元素尚未删除。

function update_prices(){
      var mytable=$("#pricestable");
      var lastpricecell = mytable.find('td[validity="count_it"]').last();
}

最后,update_prices()函数可以正常工作,然后删除DOM元素。

答案 12 :(得分:0)

引用@David回答:

当您想要使用其他功能时,例如。 html()就像我的情况一样,不要忘记在新函数中添加return:

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

答案 13 :(得分:0)

此。

$.each(
  $('#some-element'), 
        function(i, item){
            item.addEventListener('DOMNodeRemovedFromDocument',
                function(e){ console.log('I has been removed'); console.log(e);
                })
         })

答案 14 :(得分:0)

Adam's的扩展名,如果您需要防止默认设置,可以通过以下方法解决:

$(document).on('DOMNodeRemoved', function(e){
        if($(e.target).hasClass('my-elm') && !e.target.hasAttribute('is-clone')){
            let clone = $(e.target).clone();
            $(clone).attr('is-clone', ''); //allows the clone to be removed without triggering the function again

            //you can do stuff to clone here (ex: add a fade animation)

            $(clone).insertAfter(e.target);
            setTimeout(() => {
                //optional remove clone after 1 second
                $(clone).remove();
            }, 1000);
        }
    });

答案 15 :(得分:0)

我们还可以使用DOMNodeRemoved:

$("#youridwhichremoved").on("DOMNodeRemoved", function () {
// do stuff
})