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 に答える