首页 > 解决方案 > d3 嵌套数据模型的更新模式

问题描述

我一直在努力处理在 d3 中更新嵌套数据的问题,代码:

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)

  tr.enter().append('tr')

  var td = tr.selectAll("td")
    .data(d=>d.values )
    .text(d=>d)

  td.enter().append('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)
}

上面代码的问题是 d3 没有渲染第一次运行的 update(data),如果注释掉 ref() 函数,d3 只是不会将新数据附加到 html 中。

标签: javascriptd3.js

解决方案


我知道这可能是一个需要重复回答的问题,但我仍然认为它可能对许多不熟悉 d3 的开发人员有用。另外,我在这里引用的博客确实非常有用。

为了克服 d3 v3 的可用性问题,引入了一个新的选择类merge

马克的话:

D3 4.0 移除了 enter.append 的魔力。(事实上​​,D3 4.0 完全消除了输入和普通选择之间的区别:现在只有一类选择。)取而代之的是一个新的 selection.merge 方法可以统一输入和更新选择:

你可以在这里阅读更多内容:d3 CHANGES#selection

另外,我看到了这个我想分享的博客:https ://medium.com/@mbostock/what-makes-software-good-943557f8a488

在您的示例中,使用相同的merge逻辑,这是代码段:

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 rowenter = tr.enter().append('tr')

  var td = tr.merge(rowenter).selectAll("td span")
    .data(d=>d.values )
    .text(d=>d)

  td.enter().append('td').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
      }
    })
    update(data)
  }, 1000)
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<table id="gogo">

</table>

希望这可以帮助。


推荐阅读