document.createDocumentFragmentまたはdocument.createElementを使用する必要があります


97

私はドキュメントフラグメントとDOMリフローについて読んでいて、DOM要素に追加するまで、どちらもDOMに存在しないように見えるため、どのようにdocument.createDocumentFragment違うのか疑問に思いdocument.createElementました。

私はテスト(下記)を行い、すべて同じ時間(約95ms)かかりました。推測では、これは要素にスタイルが適用されていないためである可能性があり、おそらくリフローされていません。

とにかく、以下の例に基づいて、DOMに挿入するときではcreateDocumentFragmentなくなぜ使用する必要があるのかcreateElement、2つの違いは何ですか?

var htmz = "<ul>";
for (var i = 0; i < 2001; i++) {
    htmz += '<li><a href="#">link ' + i + '</a></li>';
}
htmz += '<ul>';

//createDocumentFragment
console.time('first');
var div = document.createElement("div");
div.innerHTML = htmz;
var fragment = document.createDocumentFragment();
while (div.firstChild) {
    fragment.appendChild(div.firstChild);
}
$('#first').append(fragment);
console.timeEnd('first');

//createElement
console.time('second');
var span = document.createElement("span");
span.innerHTML = htmz;
$('#second').append(span);
console.timeEnd('second');


//jQuery
console.time('third');
$('#third').append(htmz);
console.timeEnd('third');

回答:


98

違いは、ドキュメントフラグメントをDOMに追加すると、ドキュメントフラグメントが効果的に消えることです。何が起こるかというと、ドキュメントフラグメントのすべての子ノードが、ドキュメントフラグメントを挿入するDOMの場所に挿入され、ドキュメントフラグメント自体は挿入されません。フラグメント自体は存在し続けますが、現在は子がありません。

これにより、DOMに複数のノードを同時に挿入できます。

var frag = document.createDocumentFragment();
var textNode = frag.appendChild(document.createTextNode("Some text"));
var br = frag.appendChild(document.createElement("br"));
var body = document.body;
body.appendChild(frag);
alert(body.lastChild.tagName); // "BR"
alert(body.lastChild.previousSibling.data); // "Some text"
alert(frag.hasChildNodes()); // false

3
ご返信ありがとうございます。それは同時に複数の挿入を可能にするというが、私はdoc.createElementを使用してそれを達成することができます。唯一の違いは、最初に<span>タグで要素をラップし、次にその<span>をDOMに挿入する必要があったことです。それがcreateDocumentFragmentを使用する理由ですか?不要な要素がDOMに挿入されるのを防ぐには?
screenm0nkey

4
はい、それは間違いなくそれを使用する1つの理由です。また、ドキュメントフラグメントには任意の種類のノードを含めることができますが、要素には含めることができません。
Tim Down

3
実際、フラグメントは「消えない」わけではありません。ブラウザはその子ノードをDOMに移動します。したがって、フラグメントはまだ存在しますが、挿入後は空になります。
inf3rno 2014

1
@ inf3rno:したがって、「効果的に」という言葉の私の使用とそれに続く説明は、あなたの説明とほとんど同じです。フラグメントが子ノードなしで存在し続けることを回答で明示的に述べるべきだったと認めます。
Tim Down

1
@TimDownご回答ありがとうございます!私はあなたのポイントの権利を取得する場合は、パフォーマンス、使用に関するcreateFragmentそしてcreateElement、彼らは両方としてメモリにほぼ同じ効果を持つバッチがするのではなく、DOMを更新反復的に複数回のアップデート。の主な利点はcreateFragment、無料で追加する子要素を自由に選択できることです。私が間違っていたら訂正してください。
Xlee

9

要素とドキュメントフラグメントの作成のもう1つの非常に重要な違い:

要素を作成してDOMに追加すると、要素はDOMと子に追加されます。

ドキュメントフラグメントでは、子だけが追加されます。

次のケースを考えてみましょう:

var ul = document.getElementById("ul_test");


// First. add a document fragment:


(function() {
  var frag = document.createDocumentFragment();
  
  
  var li = document.createElement("li");
  li.appendChild(document.createTextNode("Document Fragment"));
  frag.appendChild(li);
  
  ul.appendChild(frag);
  console.log(2);
}());

(function() {
  var div = document.createElement("div");
  
  
  var li = document.createElement("li");
  li.appendChild(document.createTextNode("Inside Div"));
   div.appendChild(li);
  
  ul.appendChild(div);
}());
Sample List:
<ul id="ul_test"></ul>

その結果、この不正なHTML(空白が追加されます)になります

<ul id="ul_test">
  <li>Document Fragment</li>
  <div><li>Inside Div</li></div>
</ul>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.