如果在 D3.js 中的第二个参数指定数据方法,则现有元素未定义
If you specify a data method the second argument in D3.js, existing elements are undefined
如果在 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
因为如果您为 .data
函数指定第二个参数,则该参数的结果将是绑定到元素的值。没有第二个参数,数据由索引绑定。因为您要返回 d
,所以它将受值约束。由于没有数据绑定到现有的 p
元素,它们的数据是 undefined
,与您的 dataset
数组中的任何值都不匹配,因此它会处理您的所有数据dataset
数组作为新值,为它们创建新的占位符 p
元素。未定义的将在 exit
选项中。
有关详细说明,请参阅 https://github.com/mbostock/d3/wiki/Selections#data。
当我阅读@Ben Lyall 的回答时我仍然不清楚(抱歉 Ben,不是你,是我......)并且我通过阅读 wiki 肯定不清楚(我认为他们弄反了),所以我通过代码进行追踪以查看发生了什么...
首先,值得记住的是 selection
是 groups
的数组,group
是 nodes 的数组.如果有多个group
,相同的数据绑定到所有groups
.
将数据绑定到每个 group
时,d3 在两个单独的阶段调用 key 函数,首先构建一个组中所有节点的关联数组,使用 key 函数中的 returned 值作为键,第二个导出每个数据数组元素的键。然后用于查找节点数组,如果查找成功,则将数据元素绑定到其匹配节点,并将该节点添加到更新选择中。
在第一阶段,key 为 node 中的每个 node 调用一次=15=],this
上下文设置为 节点 。 d
参数是节点上的绑定数据,i
参数是[=77]节点的索引=]节点在group
。每个 node 的值 returned 和 node 本身被添加到 collection以节点为值的键值对和 key 函数的 return 值作为键。
在第二个阶段中,key 在第一个阶段中对每个 element 调用一次数据数组的维度,this
上下文设置为数据数组。 d
参数是数据数组的 元素 ,i
参数是数据数组中元素的索引。值 returned 用于查找集合,如果找到匹配项,则将该节点放入更新选择中。
因此,正如@Ben Lyall所说,key函数中的d
,就[=63而言=]defining keys,是之前绑定在节点上的数据。 (d3 在节点上添加了一个 __data__
成员)。当key用于限定数据元素时,d
为数据数组元素。这就是为什么您会看到四个节点的 undefined
和两个数据元素的预期值。
也就是说,没有理由认为密钥必须是 d
的函数。
试试这个...
<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>
在phase1中,d是绑定数据,没有定义,所以关键函数returns是节点的文本。在 phase2 中,d 是数据值,因此它们是 returned。因为phase2中的none个key与phase1中的key匹配,所以没有更新组。
矫枉过正,你也可以把它和这个混为一谈...
d = d || dataset[i];
因为 key 函数 return 在两个阶段中 i = 0 和 1 的值相同,第一个2个节点被认为是更新节点,因为所有的数据都是根据key函数绑定的,所以enter组是空的。
但最有用的情况是如果您有这样的数据...
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;
})
这是结果...
<div id="hoge">
<p class="update">C</p>
<p>A</p>
<p>Z</p>
<p class="update">X</p>
<p class="enter">4</p>
<p class="enter">9</p>
</div>
在阶段 1 中,所有节点都包含在以文本内容为键的集合中。在阶段2中,数据值用于查找集合,并且在C和X上有匹配,因此它们在更新集合中,没有匹配的数字在输入选择中。
您可能应该只使用 .data(dataset),然后这会将数据绑定到前两段。剩余的两个元素应该在 .exit() 中可用,因此您可以 .remove() 它们或其他东西(也许向它们添加一些其他数据,如默认数据)。
如果在 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
因为如果您为 .data
函数指定第二个参数,则该参数的结果将是绑定到元素的值。没有第二个参数,数据由索引绑定。因为您要返回 d
,所以它将受值约束。由于没有数据绑定到现有的 p
元素,它们的数据是 undefined
,与您的 dataset
数组中的任何值都不匹配,因此它会处理您的所有数据dataset
数组作为新值,为它们创建新的占位符 p
元素。未定义的将在 exit
选项中。
有关详细说明,请参阅 https://github.com/mbostock/d3/wiki/Selections#data。
当我阅读@Ben Lyall 的回答时我仍然不清楚(抱歉 Ben,不是你,是我......)并且我通过阅读 wiki 肯定不清楚(我认为他们弄反了),所以我通过代码进行追踪以查看发生了什么...
首先,值得记住的是 selection
是 groups
的数组,group
是 nodes 的数组.如果有多个group
,相同的数据绑定到所有groups
.
将数据绑定到每个 group
时,d3 在两个单独的阶段调用 key 函数,首先构建一个组中所有节点的关联数组,使用 key 函数中的 returned 值作为键,第二个导出每个数据数组元素的键。然后用于查找节点数组,如果查找成功,则将数据元素绑定到其匹配节点,并将该节点添加到更新选择中。
在第一阶段,key 为 node 中的每个 node 调用一次=15=],this
上下文设置为 节点 。 d
参数是节点上的绑定数据,i
参数是[=77]节点的索引=]节点在group
。每个 node 的值 returned 和 node 本身被添加到 collection以节点为值的键值对和 key 函数的 return 值作为键。
在第二个阶段中,key 在第一个阶段中对每个 element 调用一次数据数组的维度,this
上下文设置为数据数组。 d
参数是数据数组的 元素 ,i
参数是数据数组中元素的索引。值 returned 用于查找集合,如果找到匹配项,则将该节点放入更新选择中。
因此,正如@Ben Lyall所说,key函数中的d
,就[=63而言=]defining keys,是之前绑定在节点上的数据。 (d3 在节点上添加了一个 __data__
成员)。当key用于限定数据元素时,d
为数据数组元素。这就是为什么您会看到四个节点的 undefined
和两个数据元素的预期值。
也就是说,没有理由认为密钥必须是 d
的函数。
试试这个...
<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>
在phase1中,d是绑定数据,没有定义,所以关键函数returns是节点的文本。在 phase2 中,d 是数据值,因此它们是 returned。因为phase2中的none个key与phase1中的key匹配,所以没有更新组。
矫枉过正,你也可以把它和这个混为一谈...
d = d || dataset[i];
因为 key 函数 return 在两个阶段中 i = 0 和 1 的值相同,第一个2个节点被认为是更新节点,因为所有的数据都是根据key函数绑定的,所以enter组是空的。
但最有用的情况是如果您有这样的数据...
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;
})
这是结果...
<div id="hoge">
<p class="update">C</p>
<p>A</p>
<p>Z</p>
<p class="update">X</p>
<p class="enter">4</p>
<p class="enter">9</p>
</div>
在阶段 1 中,所有节点都包含在以文本内容为键的集合中。在阶段2中,数据值用于查找集合,并且在C和X上有匹配,因此它们在更新集合中,没有匹配的数字在输入选择中。
您可能应该只使用 .data(dataset),然后这会将数据绑定到前两段。剩余的两个元素应该在 .exit() 中可用,因此您可以 .remove() 它们或其他东西(也许向它们添加一些其他数据,如默认数据)。