D3变化检测如何工作? [英] How does D3 change detection work?

查看:84
本文介绍了D3变化检测如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我有一个JSON对象数组. D3如何确定将哪些放入enter()集中?

If I have an array of JSON objects. How does D3 determine which ones go in the enter() set?

如果我有一个对象数组,就像这样:

If I have an array of objects, like so:

var data = [
  {label:'a', value:1},
  {label:'b', value:3},
  {label:'c', value:2}
]

然后将其绑定到选择内容:

Then I bind it to a selection:

var bars = vis.selectAll("rect.bar")
  .data(data)

enter集现在包含所有这些数据.如果我现在更改数据:

The enter set now contains all of this data. If I now change the data:

var data = [
  {label:'a', value:99},
  {label:'c', value:2}
  {label:'b', value:3},
]

D3如何判断哪些值是更新,移动或新的?它是在对象标识上完成的吗?有没有办法让它使用标签字段来填充输入集?

How does D3 tell if the which values are updated, moved, or new? Is it done on object identity? Is there a way to make it use the label field to populate the enter set?

推荐答案

如果我正确理解了您的问题,那么您想知道D3如何将给定对象与给定DOM元素相关联.

If I understand your question correctly, you want to know how D3 associates a given object to a given DOM element.

默认情况下,如果您未设置键功能(有关更多信息,请参见下文),则对象按其顺序关联.根据API:

By default, if you don't set a key function (more on that below), the objects are associated by their order. According to the API:

...数据中的第一个基准被分配给第一个选定的元素,第二个基准被分配给第二个选定的元素,依此类推.

...the first datum in data is assigned to the first selected element, the second datum to the second selected element, and so on.

在下面的示例中让我们看看.第一个数组是这样的:

Let's see this in the following example. The first array is this:

var data = [{
    label: 'a',
    value: 1
}, {
    label: 'b',
    value: 3
}, {
    label: 'c',
    value: 2
}];

第二个数组也有3个对象.但是请注意更改:第一个是标签c,第三个是标签a.它们被交换了:

The second array has, also, 3 objects. But pay attention to the change: the first one is the label c, and the third one is the label a. They are swapped:

var data2 = [{
    label: 'c',
    value: 99
}, {
    label: 'b',
    value: 2
}, {
    label: 'a',
    value: 3
}];

因此,第一个数据中相对于a的条将在第二个数据中获得c的值.查看演示,单击按钮:

Because of that, the bar relative to a in the first data will get the value of c in the second one. Check the demo, clicking the button:

var svg = d3.select("svg");

var data = [{
  label: 'a',
  value: 1
}, {
  label: 'b',
  value: 3
}, {
  label: 'c',
  value: 2
}];

var data2 = [{
  label: 'c',
  value: 99
}, {
  label: 'b',
  value: 2
}, {
  label: 'a',
  value: 3
}];

var xScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)])
  .range([0, 260]);

var yScale = d3.scaleBand()
  .domain(data.map(d => d.label))
  .range([10, 140])
  .padding(0.3);

var rects = svg.selectAll("foo")
  .data(data)
  .enter()
  .append("rect");

rects.attr("x", 40)
  .attr("y", d => yScale(d.label))
  .attr("height", yScale.bandwidth)
  .attr("width", d => xScale(d.value))
  .attr("fill", "teal");
  
d3.axisLeft(yScale)(svg.append("g").attr("transform", "translate(40,0)"))

d3.select("button").on("click", function() {

  xScale.domain([0, d3.max(data2, d => d.value)]);

  rects.data(data2);

  rects.transition()
    .duration(1000)
    .attr("width", d => xScale(d.value))

})

<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Click</button>
<br>
<svg></svg>

如您所见,单击按钮后的图表显然不正确.

As you can see, the chart after clicking the button is clearly incorrect.

为避免这种情况,请确保在数据数组更改时,以前绑定到标签a的DOM元素仍将绑定到该标签a,我们必须使用一个键函数:

To avoid that, making sure that the DOM element previously bound to the label a will still be bound to that label a when the data array changes, we have to use a key function:

可以指定一个键函数来控制将哪个数据分配给哪个元素,从而代替默认的索引索引.依次为每个选定元素评估此键函数,将其传递为当前数据(d),当前索引(i)和当前组(节点),并将其作为当前DOM元素(nodes [i]) .然后,还将针对数据中的每个新基准评估键函数,并传递当前基准(d),当前索引(i)和组的新数据,并将其作为组的父DOM元素.给定键的数据与匹配键一起分配给元素.如果多个元素具有相同的键,则将重复的元素放入退出选择中;否则,将其添加到退出选择中.如果多个数据具有相同的键,则将重复的数据放入回车选择中.

A key function may be specified to control which datum is assigned to which element, replacing the default join-by-index. This key function is evaluated for each selected element, in order, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element (nodes[i]). The key function is then also evaluated for each new datum in data, being passed the current datum (d), the current index (i), and the group’s new data, with this as the group’s parent DOM element. The datum for a given key is assigned to the element with the matching key. If multiple elements have the same key, the duplicate elements are put into the exit selection; if multiple data have the same key, the duplicate data are put into the enter selection.

在您的情况下,这将是关键功能:

In your case, this would be the key function:

.data(data, d => d.label)
//key-------^

检查完全相同的代码,但具有按键功能:

Check the exact same code, but with a key function:

var svg = d3.select("svg");

var data = [{
  label: 'a',
  value: 1
}, {
  label: 'b',
  value: 3
}, {
  label: 'c',
  value: 2
}];

var data2 = [{
  label: 'c',
  value: 99
}, {
  label: 'b',
  value: 2
}, {
  label: 'a',
  value: 3
}];

var xScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)])
  .range([0, 260]);

var yScale = d3.scaleBand()
  .domain(data.map(d => d.label))
  .range([10, 140])
  .padding(0.3);

var rects = svg.selectAll("foo")
  .data(data, d => d.label)
  .enter()
  .append("rect");

rects.attr("x", 40)
  .attr("y", d => yScale(d.label))
  .attr("height", yScale.bandwidth)
  .attr("width", d => xScale(d.value))
  .attr("fill", "teal");
  
d3.axisLeft(yScale)(svg.append("g").attr("transform", "translate(40,0)"))

d3.select("button").on("click", function() {

  xScale.domain([0, d3.max(data2, d => d.value)]);

  rects.data(data2, d => d.label);

  rects.transition()
    .duration(1000)
    .attr("width", d => xScale(d.value))

})

<script src="https://d3js.org/d3.v4.min.js"></script>
<button>Click</button>
<br>
<svg></svg>

您可以看到,尽管新数据数组中对象的顺序不同(c是第三个,现在c是第一个),但这并没有.没关系,因为D3考虑到label属性将数据绑定到每个DOM元素.

You can see that, despite the order of the objects being different in the new data array (c was the third one, now c is the first one), this doesn't matter, because D3 is binding the data to each DOM element taking into account the label property.

这篇关于D3变化检测如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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