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

phr*_*ist 5 javascript svg dom d3.js

我正在使用d3计时器为元素设置动画,我希望计时器在元素被删除时停止.这样做的简单方法是什么?

这是一个JS小提琴来说明我的问题.我该怎么替换这一行?

  if (rect.empty()) {
Run Code Online (Sandbox Code Playgroud)

我意识到我可以通过改变它来使它工作:

  if (d3.select("rect").empty()) {
Run Code Online (Sandbox Code Playgroud)

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

alt*_*lus 1

有两个 DOM 功能可用于完成您正在寻找的任务,而这根本不需要 D3。它们都适合您,但复杂性和灵活性会有所不同。

1.使用直播 HTMLCollection

以及接口DocumentElement提供了类似的方法来根据指定的条件检索元素:

所有这些方法都将返回live 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
Run Code Online (Sandbox Code Playgroud)
<svg id="s">
  <rect id="r"/>
</svg>
Run Code Online (Sandbox Code Playgroud)

还有一些可用的属性可以提供对live HTMLCollectionNodeLists 的访问,这些属性可用于进一步的遍历:

但请注意,NodeLists 不能保证自己是活动的;你必须检查文档。以下两个方法将返回非活动NodeList,因此不能用于这些目的。

如果您需要他们提供的灵活性,您可以选择选项 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
Run Code Online (Sandbox Code Playgroud)
<svg id="s">
  <rect id="r"/>
</svg>
Run Code Online (Sandbox Code Playgroud)