【问题标题】:d3.js should I detach event listener on exit/remove?d3.js 我应该在退出/删除时分离事件侦听器吗?
【发布时间】:2013-08-22 13:46:14
【问题描述】:

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

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

【问题讨论】:

  • 移除元素也应该移除事件监听器。
  • @LarsKotthoff 你的意思是开发者应该在移除元素时(手动)移除事件还是 D3 应该为我们做这件事?
  • 您不能将事件附加到任何内容。它会在移除元素时自动移除事件处理程序。

标签: performance events memory-leaks d3.js


【解决方案1】:

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

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

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,things are a little more complicated

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多