D3中绑定数据时,索引代表什么?

When binding data in D3, what does the index represent?

当我在下面的例子中看到传递给步骤3的数据绑定函数的索引值时,我有点惊讶:

1) 创建两个包装 div,每个 div 都绑定一个数据数组

2) 在每个包装器中创建两个 "sub-divs",每个

绑定一个数组

3) 向每个"sub-div"

追加p个元素

由于元素的嵌套方式,我希望在步骤 3 中看到索引 0,1 传递给数据绑定函数。相反,我看到索引 0,1,2,3。

var data = d3.select("#data");
var idx = d3.select("#indexes");

//---- STEP 1
//create two divs with [1, 4] and [7, 10] bound
var dbox = data.selectAll("tbody").data([[1, 4], [7, 10]]);
dbox.enter().append("div").text(function(d,i){return "Group " + i });
dbox.exit().remove();
dbox.style({"clear":"both","padding":"5px","border":"1px solid #dddddd","overflow":"hidden","margin-bottom":"10px"});

//---- STEP 2
//create sub-divs
var tr = dbox.selectAll("div").data(function(d,i){
  return d.map(function(d,i,a){ return [d, d+1, d+2]; }); //return an array of arrays [[x,y,z], [a,b,c]]
});
tr.enter().append("div").text(function(d,i){return "Index " + i});
tr.exit().remove();
tr.style({"clear":"both","overflow":"hidden","padding":"2px","border":"1px dotted #dddddd","margin-top":"5px"});

//---- STEP 3
//add text (and record indexes in the "INDEXES" section)
//since the tr selection is grouped--with two "tr" divs per "dbox", I expected to see indexes of 0,1 only, instead I see 0, 1, 2, 3.
var td = tr.selectAll("p").data(function(d,i){
  idx.append("p").text(i); //track the indexes
  return d;
})
td.enter().append("p");
td.exit().remove();
td.text(function(d,i){return d}).style({});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="data">
  
</div>

<div id="indexes" style="clear:both;padding-top:20px;">
  <p>INDEXES</p>
  
</div>

我认为这里的混淆是,当使用 .attr() 或 .style() 等方法对选择进行操作时,传递给函数参数的索引表示元素在其父组中的索引。

使用 .data() 方法绑定数据时,传递给函数参数的索引表示父元素的索引。这就是拉尔斯在他的评论中所表达的意思。

我想这是有道理的,因为 D3 选择使用固定的两级层次结构(尽管听起来可能 change in the future)。因此,当您绑定新数据时,选择的层次结构会发生变化。 IE。父元素不再嵌套在选择中。

这是一个说明性的例子:

var L1 = d3.select("div#boxes");
L1.append("p").text("Level 1");

var L2 = L1.selectAll("div").data([1,2]);
L2.enter().append("div");

L2.append("p").text(function(d,i){return "Level 2"})

var L3 = L2.selectAll("div").data(function(d,i){
    return [i,i];
});
L3.enter().append("div");
L3.append("p").text(function(d,i){return "Level 3 - Index during data binding: "+d+". Index after appended: "+i+"." })

var L4 = L3.selectAll("div").data(function(d,i){
    return [i,i];
});
L4.enter().append("div");
L4.append("p").text(function(d,i){return "Level 4 - Index during data binding: " +d+". Index after appended: "+i+"."})
div{
    padding:5px;
    margin:5px;
    border:1px solid #555555;
}

p{
    font-family:Arial, Helvetica, sans-serif;
    font-size:13px;
}

#indexes p{
    float:left;
    margin-left:5px;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="boxes">
</div>

selectAll 只是将选择中的所有元素提升到父节点(忽略组结构)并将提供的选择器依次应用于每个新父节点以在其上形成新组。在此之后,选择中没有对先前父节点的引用,该状态丢失。

tr.selectAll("p")tr 中的所有 div(其中 2x2 = 4 个)提升为父节点,并根据绑定到它们的数据形成输入选择。因此有 4 个组(tr 中的每个 div),每个组有 3 个成员(绑定在父 div 上的数据的第一个维度的长度为 3)。对先前父节点的引用将被丢弃。

if values in selection.data(values)是函数,那么它的 d 参数是绑定在父组上的数据,而 i 是组索引。

如果values不是一个函数,那么相同的数据将绑定到每个组。