6

在 d3 中,selection.select具有从原始选择中的父节点继承数据的副作用。这在父节点和子节点之间共享数据的情况下是可取的,这样绑定到父节点的更新数据将被推送到子节点,而无需在每个级别进行数据连接。

但是对于绑定到父级的数据和绑定到子级的数据之间没有明确关系的情况呢?在这种情况下,selection.select可能会很隐蔽,因为只需选择一个节点,就会导致该节点的数据被不相关的父数据破坏。

避免这种情况的最佳技术是什么?我可以想到几个选项,但似乎都不太好:

  1. selection.selectAll除了需要隐式数据继承的情况外,始终在任何地方使用。然而,这并不理想,因为它使用了selection.select不一致的d3.select方法来选择单个节点(这正是我想要做的selection.select)。

  2. d3.select后代选择器一起使用,而不是selection.select隔离特定节点。使用的方便selection.select之处在于它隐式地将选择限制为起始选择的后代。使用选择器实现这一点并不是那么好。

就个人而言,我不喜欢在 API 中一些最常用的函数的一种特定形式中产生 DOM 状态修改副作用。我想我会发现如果有一个明确的调用,比如selection.update(selector)selection.appendand对称,我会更容易理解selection.insert

但是在当前的 API 中,我想知道是否有其他机制可以在使用时有效地打破继承selection.select

4

2 回答 2

1

我最终在 D3 Github 上提交了一个问题:https ://github.com/mbostock/d3/issues/1443 。没有任何解决方案,但是(我认为)对这个问题进行了有趣的讨论。在最底部,Mike 确实提供了一种可行的解决方法,为方便起见,我将在此处粘贴:

这不是一个很好的答案,但可以防止数据继承的一种方法是拥有一个没有绑定数据的中间节点。

var intermediary = selection.append("div")
    .datum(function() { return null; });

然后,来自中介的任何选择都不会传播来自父选择的数据。但当然,DOM 中的中间节点有些不幸。

于 2013-08-20T05:42:09.410 回答
0

您可以使用:

d3.select(selection.node().querySelector(selector))

在这个jsfiddle中查看它的实际效果,它使用 selectWithoutDataPropagation() 方法扩展了选择原型。

于 2017-08-24T15:40:55.357 回答