检测节点何时被删除(或从 DOM 中删除,因为父节点是)

Detect when a node is deleted (or removed from the DOM because a parent was)

我想检测节点(比如 nodeX)何时不再可用,要么是因为它已被删除,要么是因为它的父节点(或其父节点)被删除。

到目前为止,我能想到的就是使用 Mutation Observer 查看页面上的任何删除,并检查删除的节点是 nodeX 还是有 nodeX 作为后代。

有没有更简单的方法?


请注意:据我了解,链接问题(即此问题 "is a duplicate of")问的是 "how can I detect a [direct] deletion of a node"。我的问 "How can I detect the deletion of a node or its parent (or any other ancestor)".

据我所知,这对于变异观察者来说并不简单:您需要检查每个删除的节点以查看它是否是祖先。

这是我要确认或否认的。

据我了解,这与链接的问题不同。

这在堆栈溢出之前已经被问过。 How to detect element being added/removed from dom element?

如果你只想检查某个特定时间点是否存在某些东西,你显然可以这样做:

if (!document.querySelector(".nonexistent")) {
  console.log("doesn't exist");
}

否则 Mutation Observers 是您唯一的选择。

这是一个识别元素如何被删除的实现(直接删除或因为父元素被删除

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>

如果移除的子树在从文档中移除后发生变异,则接受的答案将失败。例如:

target.parent.remove();
target.remove();

将为 parent 节点删除生成一个对突变观察器的调用(目标节点删除不会报告给观察器,因为它发生在子树已经从文档中删除时)。

var parentMatch = nodes.some(parent => parent.contains(target));

在接受的答案中将 return 错误,因为目标不再是 child。问题是突变事件报告是批处理的,您不能依赖节点移除时的状态与调用突变观察器时的状态保持一致。

为此,面对与提问者类似的问题,我创建了一个目标节点祖先的WeakSet。使用附加到文档根的突变观察器,我比较了针对该集合和目标的突变。如果一个变异节点移除事件包括这个集合中的一个节点或目标节点,我知道目标节点已从树中移除。这并不意味着该节点仍被删除(它可能已被添加回来)或该节点仍然是我集合中祖先的 child。但是我可以确定这个节点在过去被移除了。

你必须小心区分突变后的 DOM 状态和你收到突变事件时的状态。