D3.js 更新嵌套数据
我试图找出如何在嵌套深度大于2级的D3应用程序中更新嵌套数据。让我们从我的代码开始 这是页面准备就绪时的jQuery处理程序D3.js 更新嵌套数据,d3.js,D3.js,我试图找出如何在嵌套深度大于2级的D3应用程序中更新嵌套数据。让我们从我的代码开始 这是页面准备就绪时的jQuery处理程序 $(function () { var data = createDataSet(); updateD3(data); setTimeout(function () { var dataAgain = createDataSet(); updateD3(dataAgain); }, 5000); });
$(function () {
var data = createDataSet();
updateD3(data);
setTimeout(function () {
var dataAgain = createDataSet();
updateD3(dataAgain);
}, 5000);
});
这里是更新函数
function updateD3(data) {
var level1 = d3
.select('body')
.selectAll('div.level-1')
.data(data);
// UPDATE existing data.
level1
.text(function (d) { return d.nameLevelOne + '-'; })
.selectAll('div.level-2')
.data(function (d) { return d.valuesLevelOne; })
.text(function (d) { return d.nameLevelTwo + '-'; })
.selectAll('div.level-3')
.data(function (d) { return d.valuesLevelTwo; })
.text(function (d) { return d.nameLevelThree + ' ' + d.count + '-'; });
// CREATE new data.
level1
.enter()
.append('div')
.attr('class', 'level-1')
.text(function (d) { return d.nameLevelOne; })
.selectAll('div')
.data(function (d) { return d.valuesLevelOne; })
.enter()
.append('div')
.attr('class', 'level-2')
.text(function (d) { return d.nameLevelTwo; })
.selectAll('div')
.data(function (d) { return d.valuesLevelTwo; })
.enter()
.append('div')
.attr('class', 'level-3')
.text(function (d) { return d.nameLevelThree + ' ' + d.count; });
// REMOVE deleted data.
level1
.exit()
.selectAll('div')
.transition()
.style('opacity', 0)
.remove();
}
这里是数据创建函数,它还记录了数据的结构
function createDataSet() {
return [
{
nameLevelOne: 'A',
valuesLevelOne: [{
nameLevelTwo: 'AA',
valuesLevelTwo: [
{
nameLevelThree: 'AAA',
count: Math.random() * 100
}
]
}]
},
{
nameLevelOne: 'B',
valuesLevelOne: [{
nameLevelTwo: 'BB',
valuesLevelTwo: [
{
nameLevelThree: 'BBB',
count: Math.random() * 100
}
]
}]
}
];
}
当我在浏览器中运行此代码时,第一个updateD3()
调用非常完美。它表明:
A
AA
AAA 24.26636815071106
B
BB
BBB 37.17236865777522
当5秒过后,创建了一个新的数据集并将其传递给另一个对updateD3()
的调用时,输出将更改为:
A-
B-
这不是我期望的结果。我没想到DOM的任何部分会被摧毁。基本上,我希望AAA
和BBB
的数字更新为新值
为什么会发生这种情况?如何仅使用更新的数据更新DOM?
我在互联网上到处寻找解决方案,但几乎每个“嵌套”数据的示例实际上只有两层深度,或者如果数据超过两层深度,则示例中没有显示更新数据的代码
非常感谢您的帮助,特别是在我为此用头撞墙6个小时后。您需要在每个级别上选择一次,而不是多次,例如
var level1 = selection.data(...);
level1.enter()...
level1.exit()...
level1....
var level2 = level1.selectAll(...).data(...);
level2.enter()...
level2.exit()...
level2...
var level3 = level2.selectAll(...).data(...);
// etc
当您多次进行选择并绑定数据时,这些选择会相互影响,并且您会在选择中得到错误的元素。每个
是什么。数据(…)
应该给出什么调用?我相信应该为level1
调用提供原始数据,但是对level2
和level3
的调用是不是分别返回d.valuesLevelOne
和d.valuesLevelTwo
的函数?我现在有点进一步了。我没有意识到您必须绑定数据,然后输入
,然后退出
,然后更新
。现在唯一的问题是,如果我更改数据并进行更新,B
、BB
和BBB
部分将消失。有什么想法吗?这是我的代码目前的一个工作版本:您只选择了div
s,所以实际上所有嵌套的div
s都在顶级选择中。您可以使用在选择器中指定的类名来修复该问题。我也简化了你的代码谢谢你,拉尔斯。这很有帮助。我唯一的最后一个问题是:在您对JSFIDLE的编辑中,每次更新时,似乎都在为AA
、AAA
、BB
和BBB
部分销毁并重新创建DOM。D3就是这样工作的,还是有办法只更新DOM(而不是销毁它)?我不知道你说的“销毁DOM”是什么意思。如果这是您的意思,那么这些元素并不是全部删除然后重新读取的。