10

私は Backbone.js アプリで documentFragments を使用することを検討してきましたが、documentFragment を親 DOM 要素に追加するときに「cloneNode」が使用されている例を見るのはなぜだろうと思っていました。

例はここで見ることができます。DocumentFragment セクションを見下ろすと、次のように表示されます。

oFrag = document.createDocumentFragment();
for (var i = 0, imax = aElms.length; i < imax; i++) {
 oFrag.appendChild(aElms[i]);
}

o.innerHTML = '';
o.appendChild(oFrag.cloneNode(true));

「oFrag」が単に追加されるのではなく複製されるのはなぜですか? 別のブログ投稿では、「cloneNode」を使用していません (比較として)。

4

4 に答える 4

7

最初のリンクは、テスト ケースのように、 autorが の代わりに使用するブログ投稿を参照しています。複数の要素 (つまり、div) に同じを指定する場合は、それを複製する必要があります。document.getElementsByTagNamedocument.getElementByIddocumentFragment

child がドキュメント内の既存のノードへの参照である場合、appendChild はそれを現在の位置から新しい位置に移動します (つまり、他のノードに追加する前に親ノードからノードを削除する必要はありません)。

これは、ノードがドキュメントの 2 つのポイントに同時に存在できないことも意味します。そのため、ノードにすでに親がある場合は、最初に削除され、次に新しい位置に追加されます。

MDN経由

ほとんどの場合、作成者 (または他の誰か) は、これを考慮せずにコードをコピーして貼り付けました。自分で試してみてください -appendChildなしで使用できcloneNode、すべて正常に動作します。

もう 1 つの可能性は、jsperf でこのテスト ケースを作成した人が、準備コードがどのように機能するかをあまり理解せず、最初のテストでaElms配列が空になり、それが機能しなくなるのではないかと心配したことです。実際、準備コードは各反復の前に実行されるため、その内容について心配する必要はありません。

最後に、パフォーマンスの問題があります。実際の挿入を本当にテストしたい場合は、ノードを複製する必要があります。それ以外の場合は、代わりにツリーの接続をテストします(上記の MDN リンクを参照)。

また、クローンを作成するとイベント リスナーが破棄されることに注意してください。

ハッピーフラグメント!;)

于 2012-12-13T11:22:33.337 に答える
2

正確にはわかりませんが、提供したリンク(パフォーマンステスト)のコンテキストではoFrag.cloneNode(true)、以前のループの実行でDOMにすでに追加された要素を再利用することに対する保護手段になる可能性があります。これにより、テストの実行が大幅に高速化されます。 。

documentFragmentsの通常のユースケースで使用する理由はありません。

于 2012-12-13T11:04:55.570 に答える
0

必要ないと思います。静的に参照されることからを切り離すためにのみ使用されたと思いますaElms。静的に参照される場合は、を呼び出すときに以前の親から削除する必要がありますappendChild。これは、このテストのパフォーマンスのためだけです。

ただし、次のコード(appendChildテストにより類似)は私にとってより理にかなっています:

var oFrag = document.createDocumentFragment();
for (var i = 0, imax = aElms.length; i < imax; i++)
    oFrag.appendChild(aElms[i].cloneNode(true));
// using it here:             ^^^^^^^^^^^^^^^^
o.appendChild(oFrag);

ただし、ノードツリーがネイティブコードで繰り返されるフラグメント全体で1回だけ呼び出すよりも時間がかかる場合があります。

http://jsperf.com/cloning-fragmentsもチェックしてください:-)

于 2012-12-13T11:05:05.147 に答える