简体   繁体   English

d3-enter-追加太多元素,好像没有绑定数据

[英]d3 - enter - appends too many elements, as if data is not bound

I'm asking this not to get code working, but to make sure I'm understanding d3 correctly. 我问这不是让代码正常工作,而是要确保我正确理解d3。 I have created a d3 bar chart example that I'm using to better understand d3's data binding and update patterns. 我创建了一个d3条形图示例,用于更好地理解d3的数据绑定和更新模式。 Fiddle is here: http://jsfiddle.net/qP9j9/22/ 小提琴在这里: http : //jsfiddle.net/qP9j9/22/

The fiddle explains the problem best, but I will also attempt an explanation below: 小提琴最好地解释了这个问题,但我还将尝试在下面进行解释:

I have split out the data binding and the view into two separate functions: 我将数据绑定和视图拆分为两个单独的函数:

var updateData = function() {

  data = generateRandomData();
  chart = d3.select('.chart').selectAll('div').data(data);
  y = d3.scale.linear().domain([0, Math.floor(d3.max(data))]).range([1,300]);

  updateChart();

};

var updateChart = function() {

  var margin = 1;
  var barWidth = (parseInt(d3.select('.chart').style('width'))/15) - margin;

  chart.transition()
        .style('height', function(d) { return y(d) + 'px' })
        .style('width', function() { return barWidth + 'px' })
        .style('left', function(d, i) { return (i * (barWidth+margin)) + 'px' });

  chart.enter().append('div')
        .style('height', function() { return 0; })
        .style('width', function() { return barWidth + 'px' })
        .style('left', function(d, i) { return (i * (barWidth+margin)) + 'px' })
        .transition()
        .style('height', function(d) { return y(d) + 'px' });

  chart.exit().remove();

};

On resize, I'm running the updateChart function. 调整大小时,我正在运行updateChart函数。 My thought there is that I'd rather not bind the data when it doesn't change, just update the view. 我的想法是,当数据不变时,我宁愿不绑定数据,而只是更新视图。 When the data actually changes, I run updateData function. 当数据实际更改时,我运行updateData函数。

Oddly, the updateData function needs to run twice in order for things to work correctly. 奇怪的是,updateData函数需要运行两次才能正常运行。 If updateData is called only once (when page first loads), then when updateChart runs, the enter() function appends the data all over again. 如果updateData仅被调用一次(第一次加载页面时),那么在运行updateChart时,enter()函数会再次将数据追加一遍。 So when the page resizes, you just get duplicate dom elements. 因此,当页面调整大小时,您只会得到重复的dom元素。

I have researched this as much as possible, including looking at some of the "Similar Questions" that were suggested, and I can certainly "work around" the problem easily enough. 我已对此进行了尽可能多的研究,包括研究了所提出的“类似问题”,我当然可以很容易地“解决”该问题。 But it feels like there's something fundamental I'm not understanding. 但这似乎是我不了解的基本知识。

The main idea behind D3 is to link data and document, so it's a bad idea to separate the two like you've done. D3的主要思想是链接数据和文档,因此像您一样将两者分开是一个坏主意。 In particular, you're using .enter() and .exit() selections, which doesn't work properly if you haven't explicitly bound data before. 特别是,您使用的是.enter().exit()选择,如果您之前没有显式绑定数据,这些选择将无法正常工作。 In your case, the .enter() selection contains the previous selection, which is why everything is added twice. 在您的情况下, .enter()选择包含先前的选择,这就是为什么将所有内容添加两次的原因。

My recommendation is two have one function that updates, not two separate ones. 我的建议是两个具有一个要更新的功能,而不是两个单独的功能。 If you absolutely do want to separate them, you need to put handling of the .enter() and .exit() selections in the updateData() function, as I've done in your updated fiddle here . 如果您确实要分离它们,则需要将.enter().exit()选择的处理放入updateData()函数中,就像我在此处更新的小提琴中所做的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM