d3.js我应该在退出/删除时分离事件监听器吗?

Ren*_*aud 11 performance events memory-leaks d3.js

我有一些代码,它们将鼠标悬停事件处理程序添加到svg圆圈以显示工具提示.我删除圆圈元素时应该删除/取消绑定这些处理程序吗?我不知道这些处理程序是否附加到svg对象,我担心它可能导致阴影dom或内存泄漏.见下面的代码:

circles.enter().append("svg:circle")
   .on("mouseenter", function(d) {
      // show tooltip
   });
circles.exit()
   .on("mouseenter", null) // necessary?
   .remove();
Run Code Online (Sandbox Code Playgroud)

exp*_*nit 19

我想你已经有了答案,但我对你如何表明这是真的感兴趣,至少在最新的Chrome中是这样.

这是删除DOM节点的D3代码部分:

function remove() {
  var parent = this.parentNode;
  if (parent) parent.removeChild(this);
}

export default function() {
  return this.each(remove);
}
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到它依赖于浏览器来清理任何关联的侦听器.

我创建了一个简单的压力测试,用D3添加/删除大量的圆形节点:

  var circles = svg.selectAll("circle")
    .data(data, function(d) { return d.id; } );

  circles.exit().remove();

  circles.enter().append("circle")
    .attr("id", function(d) { return d.id; })
    .attr("cx", function(d) { return d.x; })
    .attr("cy", function(d) { return d.y; })
    .attr( { r: 5, fill: 'blue' })
    .on("mouseenter", function(d) { console.log('mouse enter') });    
Run Code Online (Sandbox Code Playgroud)

现场版:http://bl.ocks.org/explunit/6413685

  1. 使用最新的Chrome打开上面的内容
  2. 打开开发人员工具
  3. 单击"时间轴"选项卡
  4. 单击底部的"录制"按钮
  5. 让它运行几分钟,然后再次单击该按钮以停止录制
  6. 在顶部时间轴视图中拖动选择器以覆盖几个垃圾收集锯齿模式

您会注意到DOM节点垃圾收集计数与事件侦听器垃圾收集计数相对应.实际上,由于线条是叠加的,因此您无法在下面的屏幕截图中真正区分它们:

Chrome屏幕截图

请注意,对于Internet Explorer,事情要复杂一些.

有关跟踪Chrome工具中的内存使用情况的更多提示,另请参阅此文章.