javascript - 由 var 分隔的嵌套选择失败
问题描述
我认为这更像是一个一般的 JS 问题,而不是特定于 D3 的问题。当我研究如何在 D3 中进行嵌套选择时,我最初有:
var main = d3.select('#main');
main.selectAll('div')
.data(data)
.enter().append('div').classed("parent", true)
var child = main.selectAll('.parent')
.data(function(d) { return d.children }) //=> can not read property 'children' of undefined
.enter().append('div').classed("child", true)
在阅读了一些选择文档之后,我重构了以下内容:
const main = d3.select('#main').selectAll('div')
.data(data)
.enter().append('div').classed("parent", true)
const child = main.selectAll('.parent')
.data(function(d) { return d.children })
.enter().append('div').classed("child", true)
我工作并且正在产生预期的效果。我的问题是为什么第二次调用 datamain
时会丢失对数据的引用?
编辑:我对以下内容进行了一些额外的测试:
const main = d3.select('#galaxy');
main.selectAll('div').data(data);
console.log(main); //=> ut {_groups: Array(1), _parents: Array(1)}
const main2 = d3.select('#galaxy').selectAll('div').data(data);
console.log(main2); //=> ut {_groups: Array(1), _parents: Array(1), _enter: Array(1), _exit: Array(1)}
所以似乎第一种方法没有得到_enter
和_exit
方法。
解决方案
该data
方法接受三件事:
- 数组;
- 一个函数;
- 没有。
根据 API,当您使用函数时(在您的第一种方法中就是这种情况),此函数...
...将按顺序对每个组进行评估,传递组的父数据(d,可能未定义)、组索引(i)和选择的父节点(节点),并将 this 作为组的父元素. (强调我的)
因此,此功能取决于父级的数据。这可以在源代码中看到:
data = value.call(parent, parent && parent.__data__, j, parents)
这是对您问题的解释:在您的第一种方法中,您的选择没有父母的数据。您没有多个组,这些组通常是使用 a 创建的,selectAll
后跟另一个selectAll
. 您在第一种方法中所拥有的只是 aselect
后跟 a selectAll
。
让我们在一个简单的演示中展示这一点:
var data = [{
name: "foo",
value: 10
},
{
name: "bar",
value: 17
},
{
name: "baz",
value: 42
}
];
var main = d3.select("body");
var parent = main.selectAll(null)
.data(data)
.enter()
.append('div')
.classed("parent", true)
main.selectAll('.parent')
.data(function(d) {
console.log("parent's datum is: " + JSON.stringify(d))
return 0;
});
<script src="https://d3js.org/d3.v5.min.js"></script>
另一方面,如果您有 aselectAll
后跟 another selectAll
,则您有多个组:
var data = [{
name: "foo",
value: 10
},
{
name: "bar",
value: 17
},
{
name: "baz",
value: 42
}
];
var main = d3.select("body");
var parent = main.selectAll(null)
.data(data)
.enter()
.append('div')
parent.selectAll(null)
.data(function(d) {
console.log("parent's datum is: " + JSON.stringify(d))
return d
});
<script src="https://d3js.org/d3.v5.min.js"></script>
为了完整起见,这是我制作的一个表格,其中包含 和 之间的差异select
,selectAll
注意“分组”:
表:select
和 之间的差异selectAll
。
方法 | 选择() | 全选() |
---|---|---|
选择 | 选择与选择器字符串匹配的第一个元素 | 选择与选择器字符串匹配的所有元素 |
分组 | 不影响分组 | 影响分组 |
数据传播 | 传播数据 | 不传播数据 |
推荐阅读
- java - 清除文件内容而不删除
- c# - 在 EF Core 的集合中包含每个项目的属性
- mysql - 选择不同的值多列
- javascript - 如何将 WaterfallDialogs 实现到多个应用程序 LUIS 机器人中?
- assembly - 引导时间段寄存器值变化
- cypher - 检测节点之间不必要的显式关系
- google-apps-script - GAS:发送消息时触发 onFormSubmit 问题(但它们位于“已发送”文件夹中)
- html - chrome vs IE11中的iframe onload
- sapui5 - 更改 ID 时 Smarttable 停止获取数据
- rust - 如何创建最小 BinaryHeap?