我有以下代码,它足够简单,可以更新嵌套数据模型,但 text(null)
部分似乎有点奇怪。
我不确定我这样做是否正确,或者是否有更好的方法:
var data = [
{key: 1, values:[1, 2, 3]},
{key: 2, values:[3, 4, 5]},
]
function update(data) {
var table = d3.select('#gogo')
var tr = table.selectAll('tr')
.data(data)
.text(null)
var rowEnter = tr.enter().append('tr')
var td = tr.merge(rowEnter).selectAll("td")
.data(d=>d.values)
.text(d=>d)
cellEnter = td.enter().append("td")
cellEnter.append("span")
.text(d=>d)
}
update(data)
ref()
function ref() {
setInterval(()=>{
data.map(item=> {
for (var i=0; i<3; i++) {
item.values[i] = Math.floor(Math.random() * 100) + 1
}
})
console.log(data)
update(data)
}, 1000)
}
基本上它只是呈现以下 html 代码:
<table id="gogo"><tr><td><span>1</span></td><td><span>2</span></td><td><span>3</span></td></tr><tr><td><span>3</span></td><td><span>4</span></td><td><span>5</span></td></tr></table>
请有人给我建议。
最佳答案
你说得对,还有更好的方法。现在你的代码很困惑,它有一些没有意义的东西(比如 text(null)
),最重要的是,它无法更新任何不同数量的行和单元格的表。 ..这是更新选择的最重要特征。
这是我对您的更新功能的建议:
function update(data) {
var table = d3.select('#gogo');
var tr = table.selectAll('tr')
.data(data);
var rowExit = tr.exit().remove();
var rowEnter = tr.enter().append('tr');
tr = rowEnter.merge(tr);
var td = tr.selectAll("td")
.data(d => d.values);
var cellExit = td.exit().remove();
var cellEnter = td.enter().append("td").append("span");
td = cellEnter.merge(td)
.text(d => d)
}
让我们逐行查看。
一、表选择:
var table = d3.select('#gogo');
根据该选择,我们将为行创建更新选择:
var tr = table.selectAll('tr')
.data(data);
然后,根据该更新选择,我们为行创建输入选择:
var rowEnter = tr.enter().append('tr');
之后,我们合并行的输入和更新选择:
tr = rowEnter.merge(tr);
这允许我们拥有任意数量的行。当然,要拥有真正的更新功能,我们还必须设置退出选择:
var rowExit = tr.exit().remove();
然后,对于下一个级别(即单元格),我们执行几乎相同的操作:更新、退出并使用 merge
输入选择:
var td = tr.selectAll("td")
.data(d => d.values);
var cellExit = td.exit().remove();
var cellEnter = td.enter().append("td").append("span");
td = cellEnter.merge(td)
.text(d => d);
这是使用 ref
函数的演示:
var data = [{
key: 1,
values: [1, 2, 3]
},
{
key: 2,
values: [3, 4, 5]
},
]
function update(data) {
var table = d3.select('#gogo');
var tr = table.selectAll('tr')
.data(data);
var rowExit = tr.exit().remove();
var rowEnter = tr.enter().append('tr');
tr = rowEnter.merge(tr);
var td = tr.selectAll("td")
.data(d => d.values);
var cellExit = td.exit().remove();
var cellEnter = td.enter().append("td").append("span");
td = cellEnter.merge(td)
.text(d => d)
}
update(data)
ref()
function ref() {
setInterval(() => {
data.map(item => {
for (var i = 0; i < 3; i++) {
item.values[i] = Math.floor(Math.random() * 100) + 1
}
})
update(data)
}, 1000)
}
table, tr, td {
border: 1px solid gray;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<table id="gogo"></table>
最后,只是为了向您展示现在更新函数确实可以更新表中的任意数量的元素,我重构了您的 ref
函数以创建具有随机行数(从 1 到 5)的数据,以及随机数量的单元格,也是从 1 到 5:
var data = [{
key: 1,
values: [1, 2, 3]
},
{
key: 2,
values: [3, 4, 5]
},
]
function update(data) {
var table = d3.select('#gogo');
var tr = table.selectAll('tr')
.data(data);
var rowExit = tr.exit().remove();
var rowEnter = tr.enter().append('tr');
tr = rowEnter.merge(tr);
var td = tr.selectAll("td")
.data(d => d.values);
var cellExit = td.exit().remove();
var cellEnter = td.enter().append("td").append("span");
td = cellEnter.merge(td)
.text(d => d)
}
update(data)
ref()
function ref() {
setInterval(() => {
data = d3.range(~~(Math.random() * 5) + 1).map(function(d) {
return {
key: d,
values: d3.range(~~(Math.random() * 5) + 1).map(function(d) {
return ~~(Math.random() * 20)
})
}
})
update(data)
}, 1000)
}
table,
td,
tr {
border: 1px solid gray;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<table id="gogo"></table>
关于javascript - D3 v4 更新嵌套数据,最好的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50198949/