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

我试图找出如何执行一些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 }); 

谢谢。

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

jQuery – v1.9.1

jQuery UI – v1.10.2

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

重要 :这是JQuery UI脚本(不是JQuery)的function,所以你必须加载两个脚本(jQuery和jQuery-UI)才能使它工作。 这里是例子: http : //jsfiddle.net/72RTz/

你可以使用jQuery的特殊事件

简而言之,

build立:

 (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 (o.handler && o.type !== 'destroyed') { ... } ,将if条件改为: if (o.handler && o.type !== 'destroyed') { ... }

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

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

例:

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

当元素通过绑定到DOMNodeInserted插入时,您也可以获得通知

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

 (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重写删除以及

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

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

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

看到这个答案的更多细节: JavaScript内存泄漏

所以,为了获得最佳结果,你应该钩住cleanData函数,这正是jquery.event.destroyed插件所做的:

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

对于那些使用jQuery UI的人:

jQuery UI已经重写了一些jQuery方法来实现一个remove事件,这个事件不仅在你明确地移除给定的元素的时候被处理,而且如果元素通过任何自清理的jQuery方法被从DOM中移除(例如replacehtml ,等等。)。 这基本上允许你把一个钩子放入相同的事件中,当jQuery正在“清除”与DOM元素相关的事件和数据时,会触发相同的事件。

John Resig表示 ,他对在未来版本的jQuery核心中实现这个事件持开放态度,但是我不确定它现在的位置。

我无法得到这个答案与解绑(尽pipe更新见这里 ),但能够找出解决办法。 答案是创build一个'destroy_proxy'特殊事件,触发一个'被销毁'的事件。 你把这个事件监听器放在'destroyed_proxy'和'destroy'上,然后当你想解除绑定的时候,你只要解除绑定'destroy'事件:

 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++; }); 

这是一个小提琴

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

我不确定这是否有事件句柄,所以你将不得不保留一份DOM的副本,并在某种轮询循环中与现有的DOM进行比较 – 这可能是相当恶劣的。 Firebug会这样做 – 如果您检查HTML并运行一些DOM更改,它会在短时间内突出显示Firebug控制台中黄色的更改。

或者,您可以创build一个删除function…

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

另一种方法是通过检查是否有父节点来定期检查元素是否仍然是DOM的一部分。 如果您不知道何时可以删除该元素,则可以使用一个时间间隔:

 var elem = document.querySelector('#some-element'); var intvl = setInterval(function(){ if (!elem || !elem.parentNode){ clearInterval(intvl); console.log('elem is no more'); } },10); 

http://codepen.io/oriadam/pen/QEQGjq

优点:

  • 没有使用jQuery
  • 支持任何types的删除 – jQuery,HTML操作,任何其他库

缺点:

  • 没有使用jQuery 🙂
  • 使用间隔←这可以通过附加到您怀疑的事件来改善,而不是使用间隔

这是如何创build一个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) } }); 

解决scheme,而不使用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 ); 

有了这个解决scheme,您还可以解除绑定事件处理程序。

 $("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> <div id="DivToBeRemoved"> DIV TO BE REMOVED <p>i am p (within div) <br><br><span>i am span (within div)</span></p> </div> </div> <button onclick="RemoveDiv();">Click here to remove div above</button> 

引用到@David答案:

当你想用另一个function来做,例如。 HTML()就像我的情况,不要忘记添加新的函数返回:

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

这个。

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