我想检测节点(例如,nodeX)何时不再可用,因为它已被删除或者因为它的父节点(或其父节点)被删除了。
到目前为止,我所能想到的是使用Mutation Observer查看页面上的任何删除,并检查删除的节点是nodeX还是后代的nodeX。
有更简单的方法吗?
请注意:据我所知,链接的问题(这个问题"是"的副本)问"如何检测节点的[直接]删除&#34 ;。我要求"如何检测节点或其父节点(或任何其他祖先)的删除"。
据我所知,对于变异观察者来说,这并不简单:你需要检查每个被删除的节点,看看它是否是一个祖先。
这是我想要确认或否认的。
据我了解,这与链接问题不同。
答案 0 :(得分:5)
这是一个实现,用于标识元素的删除方式(直接或因为删除了父元素)
var target = document.querySelector('#to-be-removed');
var observer = new MutationObserver(function(mutations) {
// check for removed target
mutations.forEach(function(mutation) {
var nodes = Array.from(mutation.removedNodes);
var directMatch = nodes.indexOf(target) > -1
var parentMatch = nodes.some(parent => parent.contains(target));
if (directMatch) {
console.log('node', target, 'was directly removed!');
} else if (parentMatch) {
console.log('node', target, 'was removed through a removed parent!');
}
});
});
var config = {
subtree: true,
childList: true
};
observer.observe(document.body, config);
var qs = document.querySelector.bind(document);
qs('#ul').addEventListener('click', function(){qs('ul').remove();}, false)
qs('#li').addEventListener('click', function(){qs('#to-be-removed').remove();}, false)
<ul>
<li>list item 1</li>
<li>list item 2</li>
<li id="to-be-removed">list item 3</li>
<li>list item 4</li>
</ul>
<button id="ul">remove ul</button>
<button id="li">remove li</button>
答案 1 :(得分:2)
如果删除的子树在从文档中删除后发生变异,则接受的答案将失败。例如:
target.parent.remove();
target.remove();
将生成对变异观察器的一次调用以移除父节点(当子树已从文档中删除时,目标节点移除将不会报告给观察者。)
var parentMatch = nodes.some(parent => parent.contains(target));
将返回false,因为目标不再是孩子。问题是突变事件报告是批处理的,并且您不能依赖于节点移除时的状态保持与调用突变观察者时相同的状态。
出于这个原因,面对与提问者类似的问题,我创建了一个目标节点祖先的WeakSet。使用附加到文档根目录的变异观察器,我将突变与该集合和目标进行了比较。如果突变节点移除事件包括此集合中的节点或目标节点,我知道目标节点已从树中删除。这并不意味着节点仍然被删除(它可能已经被添加回来)或节点仍然是我的集合中祖先的子节点。但我可以确定该节点在过去被删除了。
您必须小心区分突变后的DOM状态和收到突变事件时的状态。
答案 2 :(得分:0)
之前已经有人问过堆栈溢出。 How to detect element being added/removed from dom element?
如果您只是想检查特定时间点是否存在某些内容,您显然可以执行以下操作:
if (!document.querySelector(".nonexistent")) {
console.log("doesn't exist");
}
否则,Mutation Observers是您唯一的选择。