D3 v4更新嵌套数据,最好的方法 [英] D3 v4 update in nested data, the best way

查看:73
本文介绍了D3 v4更新嵌套数据,最好的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码,它足以简单地更新嵌套数据模型,但 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆