D3 v4更新嵌套数据,最好的方法 [英] D3 v4 update in nested data, the best way
问题描述
我有以下代码,它足以简单地更新嵌套数据模型,但 text(null)
部分似乎有点奇怪。
I have the following code which is simple enough to update a nested data model, but the text(null)
section seems a bit weird.
我不确定我是做得对还是有更好的方法:
I'm not sure if I'm doing it right or there is better way to do it:
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代码:
basically it just renders the following html code:
<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)
),最重要的是,它不能更新任何不同的表行数和单元格数......这是更新选择的最重要特征。
You are correct, there is a better way. Right now your code is confuse, it has some things that make no sense (like that text(null)
) and, the most important, it cannot update the table for any different number of rows and cells... and that's the most important feature of an update selection.
这是我对更新功能的建议:
This is my suggestion for your update function:
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');
根据该选择,我们将为行创建更新选择:
Based on that selection, we'll create the update selection for the rows:
var tr = table.selectAll('tr')
.data(data);
然后,根据该更新选择,我们为行创建输入选择:
Then, based on that update selection, we create the enter selection for the rows:
var rowEnter = tr.enter().append('tr');
之后,我们合并行的输入和更新选择:
After that, we merge the enter and update selection for the rows:
tr = rowEnter.merge(tr);
这允许我们拥有任意数量的行。当然,要拥有真正的更新功能,我们还必须设置退出选择:
This allows us to have any number of rows. Of course, to have a real update function, we have to set the exit selection as well:
var rowExit = tr.exit().remove();
然后,对于下一个级别,即单元格,我们做了几乎相同的事情,更新,退出和输入选择与合并
:
Then, for the next level, which are the cells, we do pretty much the same thing, an update, an exit and an enter selection with 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)的数据的函数:
Finally, just to show you that now the update function really updates the table for whatever number of elements, I refactored your ref
function to create data with a random number of rows, from 1 to 5, and a random number of cells, also from 1 to 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>
这篇关于D3 v4更新嵌套数据,最好的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!