d3.each()索引不从0开始

时间:2017-07-06 13:38:18

标签: javascript d3.js foreach each

我的问题与this非常相似。解决方案是有<div>弄乱了。我的没有<divs>

我有这个CoffeeScript代码:

data = [0, 1, 2, 3, 4]
d3.select("body")
  .data(data)
  .enter()
  .each((d, i) =>
    console.log(i, d)
  )

所需控制台输出为:

0 0
1 1
2 2
3 3
4 4

实际控制台输出为:

1 1
2 2
3 3
4 4

我可以使用以下代码获得所需的输出:

data = [0, 1, 2, 3, 4]
d3.select("body")
  .data(data)
  .each((d, i) =>
    console.log(i, d)
  ).enter()
   .each((d, i) =>
    console.log(i, d)
  )

但是两个.each()调用只是感觉不对。

2 个答案:

答案 0 :(得分:6)

d3.each() 确实从索引0开始。根据代码中的内容,您在代码中看到的是预期的行为。

这里的问题很简单:当然,页面中有一个<body>元素。您的数据数组有5个元素,其中一个元素绑定到<body>

让我们来看看。看看&#34;输入&#34;的大小。选择:

&#13;
&#13;
data = [0, 1, 2, 3, 4]
var foo = d3.select("body")
  .data(data)
  .enter();

console.log("Size of enter selection: " + foo.size())
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
&#13;
&#13;
&#13;

我们还可以显示数组中的第一个元素绑定到<body>

&#13;
&#13;
data = [0, 1, 2, 3, 4]
var foo = d3.select("body")
  .data(data)
  .enter();

console.log("Data of body: " + d3.select("body").data())
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
&#13;
&#13;
&#13;

显示这种情况的另一种方法是使用第三个参数(技术上讲,参数),这是当前组:

data = [0, 1, 2, 3, 4]
d3.select("body")
  .data(data)
  .enter()
  .each((d, i, p) =>
  //           ^---- this is the third argument
    console.log(p)
  )

这里我无法提供有效的Stack片段,因为如果我们尝试记录D3选择它会崩溃。但结果将是:

[undefined × 1, EnterNode, EnterNode, EnterNode, EnterNode]

undefined是&#34;更新&#34;选择(正文),4 EnterNode s是&#34;输入&#34;选择。这让我们解释为什么each()在您的代码中以这种方式表现。

如果你看一下源代码......

function(callback) {

    for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
        for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
            if (node = group[i]) callback.call(node, node.__data__, i, group);
        }
    }

    return this;
}

您会发现将节点与群组进行比较是有效的,您的群组同时包含&#34;更新&#34;选择和&#34;输入&#34;选择。更新选择对应于索引0,输入选择对应于索引1234

<强>解决方案

这是您想要的,请注意selectAllnull

&#13;
&#13;
data = [0, 1, 2, 3, 4]
d3.select("body")
  .selectAll(null)
  .data(data)
  .enter()
  .each((d, i) =>
    console.log(i, d)
  )
&#13;
<script src="https://d3js.org/d3.v4.js"></script>
&#13;
&#13;
&#13;

因此,正如您所看到的,选择null向我们保证我们的&#34;输入&#34;选择总是包含数据数组中的所有元素。

奖金selectselectAll的行为有所不同。大多数人认为唯一的区别是前者只选择1个元素而后者选择所有元素。但是有更微妙的差异。看看这张表:

+------------------+----------------------------------+----------------------------+
| Method           |              select()            |         selectAll()        |
+------------------+----------------------------------+----------------------------+
| Selection        | selects the first element        | selects all elements that  |
|                  | that matches the selector string | match the selector string  |
+------------------+----------------------------------+----------------------------+
| Grouping         | Does not affect grouping         | Affects grouping           |
+------------------+----------------------------------+----------------------------+
| Data propagation | Propagates data                  | Doesn't propagate data     |
+------------------+----------------------------------+----------------------------+

答案 1 :(得分:0)

看看this 基本上这个: https://stackoverflow.com/a/19726610/3433323

引用: You need to select the non-existent elements as well for the selections to work properly. ... At the moment, the selection you're matching data against contains only the one element 这意味着你只选择身体。

简而言之:

data = [0, 1, 2, 3, 4]
d3.selectAll("body")
  .selectAll('div') // add this
  .data(data)
  .enter()
  .each((d, i) =>
    console.log(i, d)
  )

jsfiddle

About selectAll