了解 D3.js 如何将数据绑定到节点

Posted

技术标签:

【中文标题】了解 D3.js 如何将数据绑定到节点【英文标题】:Understanding how D3.js binds data to nodes 【发布时间】:2012-03-17 21:34:03 【问题描述】:

我正在阅读 D3.js 文档,发现很难从文档中理解 the selection.data method。

这是文档中给出的示例代码:

var matrix = [
  [11975,  5871, 8916, 2868],
  [ 1951, 10048, 2060, 6171],
  [ 8010, 16145, 8090, 8045],
  [ 1013,   990,  940, 6907]
];

var tr = d3.select("body").append("table").selectAll("tr")
    .data(matrix)
  .enter().append("tr");

var td = tr.selectAll("td")
    .data(function(d)  return d; )
  .enter().append("td")
    .text(function(d)  return d; );

我了解大部分内容,但var td 语句的.data(function(d) return d; ) 部分是怎么回事?

我的最佳猜测如下:

var tr 语句已将一个四元素数组绑定到每个 tr 节点 var td 语句然后以某种方式使用该四元素数组作为其数据

但是.data(function(d) return d; ) 是如何实际获取该数据的,它返回了什么?

【问题讨论】:

通读this tutorial可能会有所帮助。 谢谢!我现在了解代码的.enter() 部分发生了什么。不过,我想我可能需要等待未来的教程才能了解数据键功能的情况。 我希望尽快写一个新教程,涵盖关键功能和分层选择(selectAll.selectAll)。 【参考方案1】:

当你写作时:

….data(someArray).enter().append('foo');

D3 创建一堆<foo> 元素,每个元素对应数组中的每个条目。更重要的是,它还将数组中每个条目的数据与该 DOM 元素相关联,作为 __data__ 属性。

试试这个:

var data = [ msg:"Hello",cats:42, msg:"World",cats:17 ]; 
d3.select("body").selectAll("q").data(data).enter().append("q");
console.log( document.querySelector('q').__data__ );

您将看到(在控制台中)是对象msg:"Hello",cats:42,因为它与第一个创建的q 元素相关联。

如果你以后这样做:

d3.selectAll('q').data(function(d)
  // stuff
);

d 的值原来是 __data__ 属性。 (此时,您需要确保将 // stuff 替换为返回新值数组的代码。)

Here's another example 显示绑定到 html 元素的数据以及在较低元素上重新绑定数据子集的能力:

 

【讨论】:

【参考方案2】:

理解这段代码在做什么的关键是要认识到选择是数组的数组 DOM 元素。最外面的数组称为“选择”,内部数组称为“组”,这些组包含 DOM 元素。您可以通过进入 d3js.org 的控制台并进行类似 d3.selectAll('p') 的选择来测试这一点,您将看到一个包含一个包含 'p' 元素的数组的数组。

在您的示例中,当您第一次调用 selectAll('tr') 时,您会得到一个包含所有 'tr' 元素的单个组的选择。然后matrix的每个元素都匹配到每个'tr'元素。

但是当您对该选择调用 selectAll('td') 时,选择已经包含一组 'tr' 元素。这一次,这些元素中的每一个都将成为一组“td”元素。组只是一个数组,但它也有一个 parentNode 属性引用旧的选择,在本例中是 'tr' 元素。

现在,当您在这个新选择的 'td' 元素上调用 data(function(d) return d; ) 时,d 表示绑定到每个组的父节点的数据。所以在示例中,第一组中的 'td' 将与数组 [11975, 5871, 8916, 2868] 绑定。第二组 'td' 与 [1951, 10048, 2060, 6171] 绑定。

您可以在此处阅读 mike bostock 自己对选择和数据绑定的出色解释:http://bost.ocks.org/mike/selection/

【讨论】:

谢谢!我认为这个答案很清楚,直截了当;比其他答案更重要(它也提供有用的信息,没有冒犯) 感谢链接金。说的够详细了,我看懂了。进一步推动我去bost.ocks.org/mike/nest 虽然 Phrogz 的评论有一些很好的信息并且非常有用,但这个答案清楚地解释了所提出的确切问题。我也有同样的困惑,当我看到return d; 返回 parent 节点的部分时,它点击了。令人困惑的是,某些方法在不同的层级上工作。例如,attr 作用于单个元素,与 data 不同。谢谢!【参考方案3】:

使用计数器i来显示正在使用的数据的索引。

var tr = d3.select("body").append("table").selectAll("tr")
.data(matrix)
.enter().append("tr") //create a row for each data entry, first index
.text(function(d, i)  return i); // show the index i.e. d[0][] then d[1][] etc.

var td = tr.selectAll("td")
.data(function(d)  return d; )
.enter().append("td")
.style("background-color", "yellow") //show each cell
.text(function(d,i)  return i + " " + d; ); // i.e d[from the tr][0] then d[from the tr][1]...

【讨论】:

以上是关于了解 D3.js 如何将数据绑定到节点的主要内容,如果未能解决你的问题,请参考以下文章

d3.js,将转换应用于数据?

一个初学者的指南,使用D3做数据绑定

使用 d3.js 绑定数据内的数组(动态生成具有恒定性的 d3.svg.line)

d3 数据绑定

D3.js使用过程中的常见问题(D3版本D3V4)

如何将 Xml 属性绑定到 Treeview 节点,同时将 XDocument 数据绑定到 WPF Treeview