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

时间:2013-08-22 13:46:14

标签: 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();

1 个答案:

答案 0 :(得分:17)

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

这是删除DOM节点的section of the D3 code

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

因此,您可以看到它取决于浏览器来清理任何关联的侦听器。

我创建了一个简单的压力测试,用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. 让它运行几分钟,然后再次点击按钮停止录制
  7. 在顶部时间轴视图中拖动选择器以覆盖几个垃圾收集锯齿模式
  8. 您会注意到DOM节点垃圾收集计数与事件侦听器垃圾收集计数相对应。事实上,你可以在下面的截图中真正区分它们,因为这些线是叠加的:

    Chrome Screenshot

    请注意,对于Internet Explorer,things are a little more complicated

    另请参阅this article,了解有关跟踪Chrome工具中内存使用情况的更多提示。