如果在D3.js中指定数据方法第二个参数,则现有元素未定义
<div id="hoge">
<p>C</p>
<p>A</p>
<p>Z</p>
<p>X</p>
</div>
<script>
dataset = [4,9];
d3.select("#hoge").selectAll("p").data(dataset, function(d,i){
console.log(d);
return d;
})
.enter()
.append("p")
.text(function(d){
return d;
})
的console.log
UNDEFINED
UNDEFINED
UNDEFINED
UNDEFINED
4
9
为何不明白?
为什么不跟随?
C
A
Z
X
4
9
答案 0 :(得分:1)
当我读到@Ben Lyall的答案时,我仍然不清楚(抱歉Ben,不是你,它是我......)而且我当然不清楚从阅读维基(我认为他们倒退了),所以我追查代码,看看发生了什么......
首先,值得记住的是selection
是一个groups
数组,而group
是一个节点数组。如果有多个group
,则相同的数据将绑定到所有groups
。
当将数据绑定到每个group
时,d3在两个单独的阶段中调用 键 函数,首先为所有节点构建一个关联数组。 group,使用 key 函数的返回值作为键,然后使用第二个派生每个数据数组元素的键。然后使用它来查找节点数组,如果查找成功,则将数据元素绑定到其匹配节点,并将该节点添加到更新选择中。
在第一阶段,group
中this
的每个节点都会调用 键 一次上下文设置为节点。 d
参数是节点上的绑定数据,i
参数是节点的索引group
。为每个节点返回的值和节点本身将添加到键值对的集合中,并将节点作为值和返回值 键 的功能作为键。
在第二阶段,使用{{1}为数据数组的第一维中的每个元素调用 键 一次} context设置为数据数组。 this
参数是数据数组的元素,d
参数是数据数组中元素的索引。返回的值用于查找集合,如果找到匹配项,则将该节点放入更新选择中。
因此,正如@Ben Lyall所说, 键 功能中的i
,就定义键而言,是先前绑定在节点上的数据。 (d3在节点上添加d
成员)。当密钥用于限定数据元素时,__data__
是数据数组元素。这就是为什么你看到四个节点d
和两个数据元素的期望值的原因。
话虽如此,关键字必须是undefined
的函数。
试试这个......
d
在阶段1中,d是未定义的绑定数据,因此key函数返回节点的文本。在阶段2中,d是数据值,因此返回它们。因为phase2中的所有键都不匹配phase1中的键,所以没有更新组。
只是有悖常理,你也可以把它与此混淆......
<div id="hoge">
<p>C</p>
<p>A</p>
<p>Z</p>
<p>X</p>
</div>
<script>
dataset = [4, 9];
d3.select("#hoge").selectAll("p").data(dataset, function (d, i) {
d = d || this.textContent;
console.log(d);
return d;
})
.enter()
.append("p")
.text(function (d) {
return d;
})
</script>
因为 key 函数在两个阶段中返回i = 0和1的相同值,所以前2个节点被视为更新节点,因为所有数据都是根据 键 功能绑定,输入组为空。
但最有用的情况是你有这样的数据......
d = d || dataset[i];
这是结果......
dataset = [4, 9, 'X', 'C'];
d3.select("#hoge").selectAll("p").data(dataset, function (d, i) {
d = d || this.textContent;
console.log(d);
return d;
}).attr('class', 'update')
.enter()
.append("p").attr('class', 'enter')
.text(function (d) {
return d;
})
在阶段1中,所有节点都包含在集合中,其文本内容为关键字。在阶段2中,数据值用于查找集合,并且C和X上存在匹配,因此它们位于更新集合中,并且没有匹配的数字位于输入选择中。
答案 1 :(得分:0)
因为如果为.data
函数指定第二个参数,则该参数的结果将是绑定到该元素的值。没有第二个参数,数据由索引绑定。因为您正在返回d
,所以它将受到值的约束。由于没有绑定到现有p
元素的数据,因此它们的数据为undefined
,与dataset
数组中的任何值都不匹配,因此它会处理您的所有数据dataset
数组作为新值,为它们创建新的占位符p
元素。未定义的将在exit
选择中。
有关详细说明,请参阅https://github.com/mbostock/d3/wiki/Selections#data。
答案 2 :(得分:0)
您可能应该只使用 .data(dataset) 然后这会将数据绑定到前两段。剩余的两个元素应该在 .exit() 中可用,因此您可以 .remove() 它们或其他东西(可能向它们添加一些其他数据,例如默认数据)。