我正在使用以下 CodePen,它显示一棵树作为项目的起点:https://codepen.io/augbog/pen/LEXZKK
在这支笔内部,它使用 D3.js 执行一些魔法,以便在展开树时实例化新节点:
// Update the nodes…
var node = svg.selectAll("g.node")
.data(nodes, function (d) {
return d.id || (d.id = ++i);
});
// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function (d) {
return "translate(" + source.x0 + "," + source.y0 + ")";
})
.on("click", click);
根据我对docs的理解,对于数组“节点”中大于上面发生的选择的每个条目都调用了enter()。
我失去线索的地方是下一行。
nodeEnter.append("rect")
.attr("width", rectW)
...
对于每个需要通过 Enter() 创建的新节点,此代码是否被调用一次?对我来说,它看起来不像循环,但不知何故,这些 svg 属性应用于所有节点!也许这个更新功能每个新节点都会发生一次?这听起来不太像文档中描述的 Enter() 方式。
无论如何,真正的问题——源于对接下来几行时我所处的上下文的困惑——是如何在通过 Enter() 创建这些新节点时访问原始树的属性。
// vvv ADDED LINE: Doesn't work!
if ( nodeEnter.name != "abc" )
// ^^^ ADDED LINE
nodeEnter.append("text")
.attr("x", rectW / 2)
.attr("y", rectH / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function (d) {
return d.name;
});
您可以在这里看到,通过某种魔法,将事物包装在函数中允许原始笔访问原始数组中当前元素的“name”属性。但我尝试了添加行的几种排列(包括检查条件的回调),但没有任何结果。由于我不确定访问回调的神奇属性是如何工作的,甚至不确定在评估此代码时我应该处于什么上下文中,所以我不确定检查当前属性的正确方法应该是什么。
如有任何帮助,我们将不胜感激!
Andrew Reid提到,“nodeEnter”是样本笔中节点的集合,而不是单个节点。将集合过滤为仅我想要在示例中应用属性的集合的等效代码是:
nodeEnter.append("text")
.filter(function (d) { return d.name != "abc" })
.attr("x", rectW / 2)
.attr("y", rectH / 2)
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function (d) {
return d.name;
});
需要明确的是,这些行添加了一个文本 SVG 元素,并为选择中的所有元素设置了一次的相应属性。不需要任何类型的循环。相反,在做出选择后进行新选择或应用其他过滤器是有选择地设置属性的正确方法。