jos*_*lvo 3 javascript dom dom-events mutation-observers
我想检测何时某个节点(例如nodeX)不再可用,要么是因为删除了它,要么是因为删除了它的父代(或它的父代父代)。
到目前为止,我所能想到的就是使用Mutation Observer查看页面上的所有删除,并检查删除的节点是nodeX还是后代具有nodeX。
有没有更简单的方法?
请注意:据我了解,链接的问题(该问题“是”的重复项)询问“如何检测节点的[直接]删除”。我的问题是“如何检测节点或其父节点(或任何其他祖先)的删除”。
据我了解,这对于突变观察者而言并非一帆风顺:您需要检查每个已删除的节点以查看其是否是祖先。
这是我寻求确认或否认的内容。
据我了解,这与链接的问题不同。
这是一个标识如何删除元素的实现(直接删除或由于删除父元素)
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)Run Code Online (Sandbox Code Playgroud)
<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>Run Code Online (Sandbox Code Playgroud)
如果删除的子树在从文档中删除后发生变异,则接受的答案将失败。例如:
target.parent.remove();
target.remove();
Run Code Online (Sandbox Code Playgroud)
将生成对突变观察者的一次调用,以删除父节点(目标节点删除不会报告给观察者,因为它发生在子树已从文档中删除时)。
var parentMatch = nodes.some(parent => parent.contains(target));
在接受的答案中将返回 false,因为目标不再是孩子。问题在于突变事件报告是批量的,您不能依赖节点删除时的状态与调用突变观察者时保持相同。
因此,面对与提问者类似的问题,我创建了一个目标节点祖先的 WeakSet。使用附加到文档根的突变观察器,我将突变与该集和目标进行了比较。如果突变节点删除事件包括该集合中的节点或目标节点,我知道目标节点已从树中删除。这并不意味着该节点仍然被删除(它可能已被添加回来)或者该节点仍然是我的集合中祖先的子节点。但我可以确定该节点过去已被删除。
您必须小心区分突变后的 DOM 状态和收到突变事件时的状态。