问题:

我试图了解general update pattern中d3退出选择的行为。

注意:我正在使用d3V5

Fiddle

假设我要可视化数字“ 1”。

var data = [{id:"1"}];
var text = svg.selectAll('.text').data(data);

text.enter()
    .each((d) => console.log("first append " + d))
    .append('text')
    .text(d => d.id)


一切都很好。但现在说我对“ 1”感到厌倦,并且对可视化“ 2”更感兴趣。

data = [{id:"2"}];
text = svg.selectAll('.text').data(data);

text.exit().each((d) => console.log("remove " + d)).remove();


控制台不记录{id:"1"}。此项未放置在退出选择中。

text.enter()
    .each((d) => console.log("now append " + d))
    .append('text')
    .text(d => d.id)


现在我有一个“ 1”和一个“ 2”彼此堆叠。

假设:

我曾以为,当我执行.data(data)时,d3会在dom和数据之间进行区分,并将所有没有相应条目的旧dom节点放置在退出选择的data中。我以为数据上的'id'字段可以区分这些数据元素。事实并非如此。

题:

如何在退出选择中得到{id:"1"}

或者如何删除与{id:"1"}关联的dom节点?

最佳答案

这里的混乱始于错误的假设。在我所见过的大多数d3示例中,数据具有以下格式:

[ {'id': 1, 'info': 'something'}, {'id': 2, 'info': 'something else'}, ...]


我一直以为默认情况下,selection.data()使用数据的'id'字段执行了比较。

事实证明并非如此,您需要提供自己的键功能。

D3's selection docs


  如果未指定键功能,则将数据中的第一个数据分配给第一个选定元素,将第二个数据分配给第二个选定元素,依此类推。


所以我添加了一个关键功能:

function idFunc(d) { return d ? d.id : this.id; }

var data = [{id:"1"}];
var text = svg.selectAll('text').data(data, idFunc);

text.enter()
    .append('text')
    .text(d => d.id)


然后,不再与数据数组中的项目相对应的dom节点找到了进入出口选择的方式,并且我能够将其删除。

结论:


(始终)在您.data(data, keyFunc)时在数据上定义键功能

10-04 21:30
查看更多