jQuery - 从 DOM 中删除元素时触发事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2200494/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery - Trigger event when an element is removed from the DOM
提问by sa125
I'm trying to figure out how to execute some js code when an element is removed from the page:
我试图弄清楚当一个元素从页面中删除时如何执行一些 js 代码:
jQuery('#some-element').remove(); // remove some element from the page
/* need to figure out how to independently detect the above happened */
is there an event tailored for that, something like:
是否有为此量身定制的活动,例如:
jQuery('#some-element').onremoval( function() {
// do post-mortem stuff here
});
thanks.
谢谢。
采纳答案by Philipp Munin
Just checked, it is already built-in in current version of JQuery:
刚刚检查,它已经内置在当前版本的 JQuery 中:
jQuery - v1.9.1
jQuery - v1.9.1
jQuery UI - v1.10.2
jQuery UI - v1.10.2
$("#myDiv").on("remove", function () {
alert("Element was removed");
})
Important: This is functionality of Jquery UIscript (not JQuery), so you have to load both scripts (jquery and jquery-ui) to make it work. Here is example: http://jsfiddle.net/72RTz/
重要提示:这是Jquery UI脚本(不是 JQuery)的功能,因此您必须加载这两个脚本(jquery 和 jquery-ui)才能使其工作。这是示例:http: //jsfiddle.net/72RTz/
回答by mtkopone
You can use jQuery special eventsfor this.
您可以为此使用jQuery 特殊事件。
In all simplicity,
简而言之,
Setup:
设置:
(function($){
$.event.special.destroyed = {
remove: function(o) {
if (o.handler) {
o.handler()
}
}
}
})(jQuery)
Usage:
用法:
$('.thing').bind('destroyed', function() {
// do stuff
})
Addendum to answer Pierre and DesignerGuy's comments:
回答 Pierre 和 DesignerGuy 评论的附录:
To not have the callback fire when calling $('.thing').off('destroyed')
, change the if condition to: if (o.handler && o.type !== 'destroyed') { ... }
要在调用时不触发回调$('.thing').off('destroyed')
,请将 if 条件更改为:if (o.handler && o.type !== 'destroyed') { ... }
回答by Adam
You can bind to the DOMNodeRemoved event (part of DOM Level 3 WC3 spec).
您可以绑定到 DOMNodeRemoved 事件(DOM Level 3 WC3 规范的一部分)。
Works in IE9, latest releases of Firefox and Chrome.
适用于 IE9,最新版本的 Firefox 和 Chrome。
Example:
例子:
$(document).bind("DOMNodeRemoved", function(e)
{
alert("Removed: " + e.target.nodeName);
});
You can also get notification when elements are inserting by binding to DOMNodeInserted
您还可以通过绑定到在插入元素时收到通知 DOMNodeInserted
回答by David Hellsing
There is no built-in event for removing elements, but you can create one by fake-extending jQuery's default remove method. Note that the callback must be called before actually removing it to keep reference.
没有用于删除元素的内置事件,但您可以通过假扩展 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();
Note: some problems with this answer have been outlined by other posters.
注意:其他海报已经概述了此答案的一些问题。
- This won't work when the node is removed via
html()
replace()
or other jQuery methods - This event bubbles up
- jQuery UI overrides remove as well
- 当通过
html()
replace()
或其他 jQuery 方法删除节点时,这将不起作用 - 此事件冒泡
- jQuery UI 也覆盖删除
The most elegant solution to this problem seems to be: https://stackoverflow.com/a/10172676/216941
这个问题最优雅的解决方案似乎是:https: //stackoverflow.com/a/10172676/216941
回答by zah
Hooking .remove()
is not the best way to handle this as there are many ways to remove elements from the page (e.g. by using .html()
, .replace()
, etc).
挂钩.remove()
是不处理的最佳方式,因为有许多方法可以删除页面元素(例如,通过使用.html()
,.replace()
等等)。
In order to prevent various memory leak hazards, internally jQuery will try to call the function jQuery.cleanData()
for each removed element regardless of the method used to remove it.
为了防止各种内存泄漏危害,jQuery 内部会尝试jQuery.cleanData()
为每个删除的元素调用该函数,而不管用于删除它的方法。
See this answer for more details: javascript memory leaks
有关更多详细信息,请参阅此答案:javascript memory leaks
So, for best results, you should hook the cleanData
function, which is exactly what the jquery.event.destroyedplugin does:
因此,为了获得最佳结果,您应该挂钩该cleanData
函数,这正是jquery.event.destroyed插件所做的:
http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js
http://v3.javascriptmvc.com/jquery/dist/jquery.event.destroyed.js
回答by StriplingWarrior
For those who use jQuery UI:
对于那些使用 jQuery UI 的人:
jQuery UI has overridden some of the jQuery methods to implement a remove
event that gets handled not only when you explicitly remove the given element, but also if the element gets removed from the DOM by any self-cleaning jQuery methods (e.g. replace
, html
, etc.). This basically allows you to put a hook into the same events that get fired when jQuery is "cleaning up" the events and data associated with a DOM element.
jQuery UI的重写了一些jQuery方法来实现remove
这不仅受到处理的事件,当你明确移除给定的元素,而且如果该元素被从DOM任何自洁jQuery方法移除(例如replace
,html
等) . 这基本上允许您将钩子放入当 jQuery “清理”与 DOM 元素关联的事件和数据时触发的相同事件中。
John Resig has indicatedthat he's open to the idea of implementing this event in a future version of jQuery core, but I'm not sure where it stands currently.
John Resig 表示他对在 jQuery 核心的未来版本中实现这个事件的想法持开放态度,但我不确定它目前的情况。
回答by Legends
Only jQuery is required (No jQuery UI needed)
只需要 jQuery(不需要 jQuery UI)
(I have extracted this extension from the jQuery UI framework)
(我已经从 jQuery UI 框架中提取了这个扩展)
Works with: empty()
and html()
and remove()
兼容于: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 );
With this solution you can also unbindthe event handler.
使用此解决方案,您还可以取消绑定事件处理程序。
$("YourElemSelector").off("remove");
Try it! - Example
尝试一下!- 例子
$.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>
Additional Demo - jsBin
回答by Bill Johnston
I couldn't get this answerto work with unbinding (despite the update see here), but was able to figure out a way around it. The answer was to create a 'destroy_proxy' special event that triggered a 'destroyed' event. You put the event listener on both 'destroyed_proxy' and 'destroyed', then when you want to unbind, you just unbind the 'destroyed' event:
我无法得到这个解绑定的答案(尽管更新见这里),但能够找到解决方法。答案是创建一个 'destroy_proxy' 特殊事件来触发一个 'destroyed' 事件。您将事件侦听器放在 'destroyed_proxy' 和 'destroyed' 上,然后当您想解除绑定时,您只需解除 'destroyed' 事件的绑定:
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++;
});
Here is a fiddle
这是一个小提琴
回答by Charon ME
I like mtkopone's answer using jQuery special events, but note that it doesn't work a) when elements are detached instead of removed or b) when some old non-jquery libraries use innerHTML to destroy your elements
我喜欢 mtkopone 使用 jQuery 特殊事件的回答,但请注意它不起作用 a) 当元素被分离而不是被删除或 b) 当一些旧的非 jquery 库使用 innerHTML 来破坏你的元素时
回答by Fenton
I'm not sure there is an event handle for this, so you would have to keep a copy of the DOM and compare to the existing DOM in some kind of polling loop - which could be quite nasty. Firebug does this though - if you inspect the HTML and run some DOM-changes, it highlights the changes in yellow in the Firebug console for a short time.
我不确定是否有用于此的事件句柄,因此您必须保留 DOM 的副本并在某种轮询循环中与现有 DOM 进行比较 - 这可能非常糟糕。不过,Firebug 会这样做——如果您检查 HTML 并运行一些 DOM 更改,它会在 Firebug 控制台中以黄色突出显示一小段时间的更改。
Alternatively, you could create a remove 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");