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

问题描述 投票:4回答:2

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

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

如果我这样做1000 svg元素,这是否意味着我只附加了1000个不同的听众。如果是这种情况,是否特别针对d3进行了事件委托?

javascript d3.js svg dom-events
2个回答
6
投票

@AlexW answer(部分)正确: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没有用于事件委派的本地显式方法,但解决方案非常简单明了。


3
投票

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

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

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

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

D3不进行事件委托,它只进行事件绑定。因此,如果您仍在考虑使用SVG,则可能需要实现委派using jQuery or vanilla JS

© www.soinside.com 2019 - 2024. All rights reserved.