如果我遵循正常的 D3 方式,我是否将事件侦听器添加到每个 SVG 元素?



在d3 中处理 onclick 的正常方法是

selection.append(element)
.on("click", someFunction)

如果我在 1000 个 svg 元素上这样做,这是否意味着我只附加了 1000 个不同的侦听器。如果是这种情况,是否专门针对 d3 进行事件委派?

@AlexW答案(部分)正确:D3中没有事件委托,只有事件绑定。

但是,我之所以这么说,部分原因是最好说"D3 中没有用于事件委派的本机方法">,因为实际上实现它非常容易:使用 D3 进行事件委派的丑陋替代方法是使用 d3.event.target。

例如,在这个非常简单的演示中,我们绑定了这些数据...

var data = ["foo", "bar", "baz"];

。到<g>元素内的圆圈。然后,我们将事件侦听器绑定到组,并在单击时获取每个圆的数据:

g.on("click", function() {
console.log(d3.select(d3.event.target).datum())
})

是这样的:

var svg = d3.select("svg");
var g = svg.append("g");
var data = ["foo", "bar", "baz"];
var circles = g.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("cy", 40)
.attr("cx", function(_, i) {
return 50 + 100 * i
})
.attr("r", 20)
.attr("fill", "teal");
g.on("click", function() {
console.log(d3.select(d3.event.target).datum())
})
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

这种方法的好处是,就像 jQuery 事件委托一样,它适用于在定义侦听器后创建的元素。在下面的演示中,红色圆圈:

var svg = d3.select("svg");
var g = svg.append("g");
var data = ["foo", "bar", "baz"];
var circles = g.selectAll(null)
.data(data)
.enter()
.append("circle")
.attr("cy", 40)
.attr("cx", function(_, i) {
return 50 + 75 * i
})
.attr("r", 20)
.attr("fill", "teal");
g.on("click", function() {
console.log(d3.select(d3.event.target).datum())
});
g.append("circle")
.attr("cy", 40)
.attr("cx", 275)
.attr("r", 20)
.attr("fill", "firebrick")
.datum("foobar")
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

因此,尽管 D3 没有用于事件委派的本机显式方法,但解决方案非常简单明了。

是的,这将添加 1000 个事件侦听器:

向指定元素的每个选定元素添加或删除侦听器 事件类型名称。

https://github.com/d3/d3-selection/blob/master/README.md#selection_on

如果你有 1000+ 个元素,你可能不想使用 SVG,因为 DOM 很容易被这么多元素所困扰。 使用画布等可能更有效。

D3 不执行事件委派,它只执行事件绑定。因此,如果您仍在考虑使用 SVG,您可能希望使用 jQuery 或 vanilla JS 实现委派。

下面是一个 d3 svg 事件委派实现:d3-delegate。 您可以使用以下命令下载节点模块:npm i --save d3-delegation.

单击我进入演示。

最新更新