11

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

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

1 回答 1

19

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

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

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

export default function() {
  return this.each(remove);
}

所以你可以看到它依赖于浏览器来清理任何相关的监听器。

我创建了一个使用 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') });    

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

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

您会注意到 DOM 节点垃圾回收计数与事件侦听器垃圾回收计数相对应。实际上,在下面的屏幕截图中,您无法真正将它们区分开来,因为这些线条是叠加的:

铬截图

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

另请参阅这篇文章,了解有关在 Chrome 工具中跟踪内存使用情况的更多提示。

于 2013-09-02T14:57:46.547 回答