在 d3.js 中,如何在不进行新选择的情况下检查元素是否已被删除

In d3.js, how can I check if an element has been removed without doing a new selection?

本文关键字:情况下 选择 检查 元素 删除 是否 js d3 新选择      更新时间:2023-09-26

我正在使用 d3 计时器对元素进行动画处理,我希望计时器在元素被删除后停止。什么是简单的方法?

这是一个JS小提琴来说明我的问题。我应该用什么替换此行?

  if (rect.empty()) {

意识到我可以通过将其更改为以下内容来使其工作:

  if (d3.select("rect").empty()) {

但是,如果我有很多rect元素或大量重用相同的类,则基于元素名称或类进行新的 D3 选择是一个问题。是否可以简单地刷新现有的 D3 选择以查看它是否已变为空?

有两个 DOM 功能可用于完成您正在寻找的内容,它们根本不需要 D3。它们都适合您,但复杂性和灵活性各不相同。

1. 使用实时HTMLCollection

DocumentElement 接口都提供了类似的方法,用于根据指定的条件检索元素:

  • Document.getElementsByClassName()Element.getElementsByClassName()

  • Document.getElementsByTagName()Element.getElementsByTagName()

  • Document.getElementsByClassNameNS()Element.getElementsByClassNameNS()

所有这些方法都将返回一个实时HTMLCollection,这意味着元素的集合即使在第一次检索后也会保持最新。您可以通过使用 HTMLCollection.item().namedItem() 查询集合来检查元素是否存在,或者,如果集合只包含一个元素,则查看 .length

var svg = document.getElementById("s");
// This is a live HTMLCollection.
var rects = document.getElementsByTagName("rect");
console.log(rects.length);              // 1: <rect> in collection
svg.removeChild(rects.namedItem("r"));  // remove <rect#r>
console.log(rects.length);              // 0: <rect> gone
<svg id="s">
  <rect id="r"/>
</svg>

还有一些属性可用于访问可用于进一步遍历的实时HTMLCollectionNodeList

  • ParentNode.children现场HTMLCollection
  • Node.childNodes现场NodeList

但是请注意,NodeList不能保证自己存在;您必须检查文档。以下两种方法将返回非实时NodeList,因此不能用于这些目的。

  • Document.querySelectorAll()Element.querySelectorAll()

如果您需要他们提供的灵活性,您可以选择选项 2。

2. 使用MutationObserver

为人知且被高度低估的MutationObserver界面会派上用场,只要您对 DOM 的更改感兴趣。不过,这是更复杂的方法,它允许更大的灵活性。

您创建一个新MutationObserver,提供一个回调,每次对 DOM 进行相关更改时都会调用该回调。启动观察器时,您可以通过定义感兴趣的元素和子树并传入MutationObserverInit配置对象来指定哪些更改是相关的。在回调中,您几乎可以自由地以任何您喜欢的方式对这些更改做出反应。

var svg = document.getElementById("s");
var rect = document.getElementById("r");
var observer = new MutationObserver(function(mutations) {
  // This callback will be called for all changes you configured it to listen to
  // and will provide information about every change in the array of 
  // MutationRecords. You can use this to filter and react to the changes you are
  // interested in by providing an approriate callback function. 
  var removed = mutations.filter(function(mutation) {
    return mutation.removedNodes.length > 0;
  });
  console.log(`Observed removal of ${removed.length} node(s).`)
})
 
// Listen for changes of the svg element to the child list only 
observer.observe(svg, { childList: true }); 
console.log("<rect> found: " + document.getElementById("r") != null);  // <rect> found
svg.removeChild(rect);                                                 // remove <rect>
console.log("<rect> found: " + document.getElementById("r") != null);  // <rect> gone
<svg id="s">
  <rect id="r"/>
</svg>

相关文章: