使用 d3.js 时,为什么在将新元素附加到条目选择时必须在 select 之后调用 selectAll?

eri*_*gor 6 select enter selectall d3.js

假设我们有一个没有子节点的 svg 元素:

<svg id="bargraph" width="400" height="90" ></svg>
Run Code Online (Sandbox Code Playgroud)

假设我们还有一个数据数组:

var data = [10,20,30,40,50];
Run Code Online (Sandbox Code Playgroud)

此代码正确地将新的 rect 元素附加到 svg 元素。

 d3.select("#bargraph")
 .selectAll("rect")
 .data(data)
 .enter()
 .append("rect")
 .attr("height", 10)
 .attr("width", function(d) { return d; })
 .attr("x", 0)
 .attr("y", function (d, i) { return i * 20; })
 .attr("fill", "blue");
Run Code Online (Sandbox Code Playgroud)

下面的代码不会将新的 rect 元素附加到 svg 元素。你能告诉我为什么吗?

 d3.selectAll("#bargraph rect")
 .data(data)
 .enter()
 .append("rect")
 .attr("height", 10)
 .attr("width", function(d) { return d; })
 .attr("x", 0)
 .attr("y", function (d, i) { return i * 20; })
 .attr("fill", "blue");
Run Code Online (Sandbox Code Playgroud)

And*_*eid 4

每当您附加元素时,D3 都会将它们附加到选定的父元素。您没有选择父元素,而是仅选择具有指定父元素的元素。

\n

在您的示例中,您选择所有rect具有 id 的父项bargraph,同时您可以使用以下命令成功更新这些节点:

\n
d3.selectAll("#bargraph rect").data(data).attr(...)\n
Run Code Online (Sandbox Code Playgroud)\n

但是,使用以下内容不会将项目附加到#bargraph(如您所述):

\n
d3.selectAll("#bargraph rect").data(data).enter()\n
Run Code Online (Sandbox Code Playgroud)\n

这里,D3将扫描整个文档,父元素,(d3.selectAll() ) 并返回与选择器条件匹配的每个匹配元素。然后,输入选择将为数据数组中不存在的每个元素创建一个占位符节点。这些节点是根据父元素选择创建的:

\n
\n

从概念上讲,输入选择\xe2\x80\x99s 占位符是指向\n父元素的指针(文档

\n
\n

正如我们可以选择矩形并输入圆形一样,没有任何东西将选择器和我们希望输入的元素的类型/位置联系起来。

\n

在下面的示例中,我使用 选择(并更新)SVG 圆d3.selectAll("svg circle"),但输入了一个 div - 我们可以看到该 div 附加到父选择的元素,在这种情况下d3.selectAll()是文档本身,而不是尽管我选择了 SVG(而不是主体):

\n

\r\n
\r\n
d3.selectAll("#bargraph rect").data(data).attr(...)\n
Run Code Online (Sandbox Code Playgroud)\r\n
d3.selectAll("#bargraph rect").data(data).enter()\n
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n


\n

好吧,但是为什么 D3 会这样呢?最终,我无法回答为什么,因为这是我以外的人做出的决定的结果。我敢打赌,其中一些推理可能是这样的:

\n

如果诸如此类的选择器(#bargraph rect)确定了元素的输入位置,那么根据选择器的不同,可能会遇到某些挑战:

\n
    \n
  • 如果您不想向具有 id 的元素输入元素怎么办bargraph?也许您想在其他地方输入元素(但仍然需要仅选择具有 id 的元素的特定子元素bargraph)。
  • \n
  • 如果您选择了一个类或每个 div/p/etc,新输入的元素将附加到哪个父元素?
  • \n
  • 如果选择一个元素类,您可能希望将同级元素而不是子元素附加到该类。
  • \n
\n

当然,最后两个是关于类而不是 ID,但无论选择器字符串如何,行为都应该相似(选择器字符串中的 ID、类和元素的不同行为可能会令人困惑)。所选择的方法可能被那些决定者选为对程序员来说最干净、最清晰的方法。

\n