Javascript d3.js:enter()、update、exit(),其中包含group元素

Javascript d3.js:enter()、update、exit(),其中包含group元素,javascript,d3.js,Javascript,D3.js,我的DOM结构如下所示,当我使用D3.js渲染可视化并输入、更新、退出模式时: g rect ... g rect ... g rect ... 我正在处理组中的多个元素和嵌套选择,但为了简单起见,我将用rect演示这一点。DOM通过以下方式完成: group = d3.select('.svg-content') .selectAll('g') .data(items, function (item) { return item.Id; }); gr

我的DOM结构如下所示,当我使用D3.js渲染可视化并输入、更新、退出模式时:

g
  rect
  ...
g
  rect
  ...
g
  rect
  ...
我正在处理组中的多个元素和嵌套选择,但为了简单起见,我将用rect演示这一点。DOM通过以下方式完成:

group = d3.select('.svg-content')
    .selectAll('g')
    .data(items, function (item) { return item.Id; });

groupEnter = group.enter()
    .append('svg:g')
    .attr('class','group-content');

// enter
groupEnter.append('svg:rect')
    .style('fill', '#000')
    .attr('x', function (item) { return item.x })
    .attr('y', function (item) { return item.y; })
    .attr('width', function (item) { return item.width; })
    .attr('height', function (item) { return item.height; });

// update
group.select('rect') 
    .attr('x', function (item) { return item.x })
    .attr('width', function (item) { return item.width; });

// remove
group.exit().remove();
这管用

现在我想实现以下目标:

g
  g
    rect
  ...
g
  g
    rect
  ...
g
  g
    rect
  ...
我想将rect封装在另一个组元素中

group = d3.select('.svg-content')
    .selectAll('g')
    .data(items, function (item) { return item.Id; });

groupEnter = group.enter()
    .append('svg:g')
    .attr('class','group-content');

// enter
groupEnter
    .append('svg:g') // NEW
    .attr('class','rect-content') // NEW
    .append('svg:rect')
    .style('fill', '#000')
    .attr('x', function (item) { return item.x })
    .attr('y', function (item) { return item.y; })
    .attr('width', function (item) { return item.width; })
    .attr('height', function (item) { return item.height; });

// update
group
    .select('.rect-content') // NEW
    .select('rect') 
    .attr('x', function (item) { return item.x })
    .attr('width', function (item) { return item.width; });

// remove
group.exit().remove(); // NOTE: without this, it works!

这个代码有什么问题?如果没有删除块,它可以工作,但我需要它来处理新的/删除的项目。如何使其正确?

问题是您正在选择普通
g
元素来将数据绑定到(
.selectAll('g').data(…)
)。当这些元素只有一个级别时,这可以正常工作,但由于
.selectAll()
递归工作,它将选择比嵌套结构多得多的元素

也就是说,选择包含更多的元素,这些元素“使用”绑定的数据。因此,数据最终不会与正确的元素匹配

要修复此问题,只需使选择器更具体:

group = d3.select('.svg-content')
    .selectAll('g.group-content')
    .data(...);

完成演示。

乍一看很好。你能详细说明一下它是如何工作的吗?它会删除所有的矩形。我认为该过程无法将新的g元素与数据连接起来,并且认为应该将其删除。“…但是作为.selectAll()递归工作…”-这揭示了很多秘密!谢谢你!虽然这并不是导致我来到这里的问题的答案,但我认为这是一条非常有用的信息(有点远见)