有人能解释一下D3.js中datum()和data()的区别吗?我看到两者都被使用,我不知道为什么你应该选择一个而不是另一个?


当前回答

基本上,数据和基准之间的区别是绑定元素的数量。Data用于元素列表,而datum仅指定一个元素。例如,d3.selectAll('div').data([1,2,3])意味着将一个元素列表(即1,2,3)绑定到三个不同的div。然后你可以用.enter().append('div')链接代码,为每个新元素创建一个新的div。另一方面,d3.select('div').datum(1)表示将元素1绑定到div元素。

你可能会注意到,我们也可以做一些类似d3.select(div).datum([1,2,3])的事情。它与d3.selectAll('div').data([1,2,3])不同。D3.select (div).datum([1,2,3])将[1,2,3]视为只绑定到div元素的一个元素,就像div =>[1,2,3]一样。而d3.selectAll('div').data([1,2,3])则将[1,2,3]视为一个元素列表,这样它就会将数组中的每个元素绑定到每个div元素,就像div => 1;Div => 2;3. Div =>

其他回答

这里有一些很好的链接:

D3 "数据讨论得很好()”: 了解D3.js如何将数据绑定到节点 凡人D3 Mike Bostock的D3维基

根据后者:

#选择。数据([[,]]值) 将指定的数据数组与当前选定项连接。的 指定值是数据值的数组,例如数组 数字或对象,或返回值数组的函数。 … # selection.datum((值)) 获取或设置每个选定元素的绑定数据。不像 选择。数据方法,此方法不计算连接(因此 不计算进入和退出选择)。

我认为HamsterHuey给出的解释是目前为止最好的。 为了对其进行扩展并给出差异的可视化表示,我创建了一个示例文档,该文档至少说明了数据和数据之间的部分差异。

下面的答案更多的是使用这些方法得出的一个观点,但如果我错了,我很乐意被纠正。

这个例子可以运行在下面或在这个小提琴。

const data = [1,2,3,4,5];
const el = d3.select('#root');

 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node => data: ${d}`);

const join= el
.selectAll('div.b')
.data(data);

join
.enter()
.append('div')
.classed('b', true)
.text((d, i) => `node-${i + 1} => data: ${d}`)

我认为该数据更容易掌握,因为它不做连接,但当然这也意味着它有不同的用例。

对我来说,一个很大的不同——尽管还有更多——是数据只是在d3图表上进行(实时)更新的自然方式,因为整个进入/更新/退出模式使它变得简单,一旦你得到它。

另一方面,在我看来,数据似乎更适合静态表示。在下面的例子中,我可以实现同样的结果,我在原始数组上循环,并通过索引访问数据,如下所示:

data.map((n, i) => {
 el
  .append('div')
  .classed('a', true)
  .datum(data)
  .text(d => `node-${n} => data: ${d[i]}`);
});

试试这里:https://jsfiddle.net/gleezer/e4m6j2d8/6/

同样,我认为这更容易掌握,因为你可以摆脱进入/更新/退出模式带来的精神负担,但一旦你需要更新或更改选择,你肯定会更好地诉诸于.data()。

const data = [1,2,3,4,5]; const el = d3.select('#root'); el .append('div') .classed('a', true) .datum(data) .text(d => `node => data: ${d}`); const join= el .selectAll('div.b') .data(data); join .enter() .append('div') .classed('b', true) .text((d, i) => `node-${i + 1} => data: ${d}`) /* Ignore all the css */ html { font-family: arial; } .l { width: 20px; height: 20px; display: inline-block; vertical-align: middle; margin: 10px 0; } .l-a { background: #cf58e4; } .l-b { background: #42e4e4; } .a { border-bottom: 2px solid #cf58e4; } .b { border-bottom: 2px solid #42e4e4; } <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.6.0/d3.min.js"></script> <div style="margin-bottom: 20px;"> <span class="l l-a"></span> .datum() <br /> <span class="l l-b"></span> .data() </div> <div id="root"></div>

我从迈克那里找到了正确答案:

如何处理JSON数据结构?

如果希望将数据绑定到单个SVG元素,请使用

(...).data([data])

or

(...).datum(data)

如果您希望将数据绑定到多个SVG元素

(...).data(data).enter().append("svg")

After having looked into this a bit, I've found that the answers here on SO are not complete as they only cover the case when you invoke selection.data and selection.datum with an input data parameter. Even in that scenario, the two behave differently if the selection is a single element versus when it contains multiple elements. Moreover, both of these methods can also be invoked without any input arguments in order to query the bound data/datum in the selection, in which case they once again behave differently and return different things.

编辑-我在这里发布了这个问题的更详细的答案,但下面的帖子几乎抓住了关于这两种方法的所有关键点,以及它们之间的区别。

当作为输入参数提供数据时

selection.data(data) will attempt to perform a data-join between the elements of the data array with the selection resulting in the creation of enter(), exit() and update() selections that you can subsequently operate on. The end result of this is if you pass in an array data = [1,2,3], an attempt is made to join each individual data element (i.e. datum) with the selection. Each element of the selection will only have a single datum element of data bound to it. selection.datum(data) bypasses the data-join process altogether. This simply assigns the entirety of data to all elements in the selection as a whole without splitting it up as in the case of data-joins. So if you want to bind an entire array data = [1, 2, 3] to every DOM element in your selection, then selection.datum(data) will achieve this.

警告:许多人认为select .datum(data)等同于select .data([data]),但这仅在以下情况下成立 选择区只包含一个元素。如果选择包含 那么select .datum(data)将绑定多个DOM元素 选择中的每一个元素的全部数据。在 相比之下,select .data([data])只绑定整个数据 到选择的第一个元素。这与 data的数据连接行为。

当不提供数据输入参数时

selection.data() will take the bound datum for each element in the selection and combine them into an array that is returned. So, if your selection includes 3 DOM elements with the data "a", "b" and "c" bound to each respectively, selection.data() returns ["a", "b", "c"]. It is important to note that if selection is a single element with (by way of example) the datum "a" bound to it, then selection.data() will return ["a"] and not "a" as some may expect. selection.datum() only makes sense for a single selection as it is defined as returning the datum bound to the first element of the selection. So in the example above with the selection consisting of DOM elements with bound datum of "a", "b" and "c", selection.datum() would simply return "a".

注意,即使selection只有一个元素,select .datum()和select .data()也会返回不同的值。前者返回选择的绑定数据(在上面的例子中是"a"),而后者返回数组中的绑定数据(在上面的例子中是["a"])。

希望这有助于解释选择是如何进行的。Data和select .datum()在提供数据作为输入参数和通过不提供任何输入参数查询绑定的数据时都是不同的。

PS -理解这是如何工作的最好方法是在Chrome中从一个空白的HTML文档开始,打开控制台,尝试在文档中添加一些元素,然后开始使用选择绑定数据。Data和select .datum。有时候,通过实践比阅读更容易“理解”一些东西。

基本上,数据和基准之间的区别是绑定元素的数量。Data用于元素列表,而datum仅指定一个元素。例如,d3.selectAll('div').data([1,2,3])意味着将一个元素列表(即1,2,3)绑定到三个不同的div。然后你可以用.enter().append('div')链接代码,为每个新元素创建一个新的div。另一方面,d3.select('div').datum(1)表示将元素1绑定到div元素。

你可能会注意到,我们也可以做一些类似d3.select(div).datum([1,2,3])的事情。它与d3.selectAll('div').data([1,2,3])不同。D3.select (div).datum([1,2,3])将[1,2,3]视为只绑定到div元素的一个元素,就像div =>[1,2,3]一样。而d3.selectAll('div').data([1,2,3])则将[1,2,3]视为一个元素列表,这样它就会将数组中的每个元素绑定到每个div元素,就像div => 1;Div => 2;3. Div =>