【问题标题】:How to guarantee old data is in d3's exit selection如何保证旧数据在d3的退出选择中
【发布时间】:2018-07-27 01:17:51
【问题描述】:

问题:

我试图从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节点?

【问题讨论】:

  • 您只是缺少data 方法中的关键函数,仅此而已。这肯定是重复的,我很快就会找到目标的。
  • 哦。我假设 'id' 属性在 d3 中默认用作键。我仍然无法用关键功能修复我的小提琴......也许我只是做错了。
  • @GerardoFurtado 仍然无法获得在小提琴上工作的关键功能。想试试吗?
  • 你试过data(data, d => d.id)吗?如果您不使用键功能,则默认使用数组中的索引(对于您的两个示例都是0
  • @AlexLenail 对不起,我以前在手机上,现在我在电脑上,更容易阅读代码。这里的问题不是缺少关键功能(但拥有一个总是很有趣),这里的问题是您选择了一个不存在的类(.text)。实际上,您只是没有选择任何内容(请阅读我的explanation here)。这是按标签选择的相同代码:jsfiddle.net/hbzgoeu8

标签: javascript d3.js


【解决方案1】:

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

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

我一直假设 selection.data() 默认使用数据的 'id' 字段执行差异。

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

来自D3's selection docs

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

所以我加了一个关键函数:

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) 时为您的数据定义一个关键函数

【讨论】:

  • 恐怕你在结论中的第二点是完全错误的。这与您遇到的问题无关:您不需要设置 id 属性或任何其他属性。正如我在评论中解释的那样,您遇到的问题只是一个选择问题(您选择了不存在的东西)。
  • 那么,idFunc(d) { return d ? d.id : this.id; }中推荐三元的原因是什么?什么时候去第二个分支,this是什么?
  • .data(data, function(d) { return d ? d.name : this.id; }) 来自github.com/d3/d3-selection#selection_data
  • 那只是为了检查数据是否存在。这与我的评论有什么关系?您无需在元素中设置任何id 属性,退出/进入选择仅基于基准。很清楚:jsfiddle.net/ku4e1Lbx
  • 话虽如此,我有一种强烈的感觉,你为你的真实代码写了一个答案,而不是你在这里发布的问题。在您的真实代码中,您可能已经在页面中拥有 DOM 元素,这就是为什么您需要一个三元组,因为缺少数据,元素具有 ID。但是,在您的问题中,您没有以前存在的 DOM 元素,所有内容都是通过输入选择创建的。因此,您不需要设置 ID。同样,我建议您更改答案,或删除整个 Q/A 对,因为您的答案完全错误且具有误导性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 2020-07-16
  • 1970-01-01
相关资源
最近更新 更多