Haruskah saya menggunakan document.createDocumentFragment atau document.createElement

97

Saya sedang membaca tentang fragmen dokumen dan perubahan posisi DOM dan bertanya-tanya seberapa document.createDocumentFragmentberbeda dari document.createElementyang terlihat seperti keduanya tidak ada di DOM sampai saya menambahkannya ke elemen DOM.

Saya melakukan tes (di bawah) dan semuanya membutuhkan waktu yang sama persis (sekitar 95ms). Diperkirakan, hal ini mungkin karena tidak ada gaya yang diterapkan ke salah satu elemen, jadi mungkin tidak ada perubahan posisi.

Bagaimanapun, berdasarkan contoh di bawah ini, mengapa saya harus menggunakan createDocumentFragmentdaripada createElementsaat memasukkan ke dalam DOM dan apa perbedaan antara keduanya.

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');
screenm0nkey
sumber

Jawaban:

98

Perbedaannya adalah fragmen dokumen menghilang secara efektif saat Anda menambahkannya ke DOM. Apa yang terjadi adalah semua simpul anak dari fragmen dokumen disisipkan di lokasi di DOM tempat Anda memasukkan fragmen dokumen dan fragmen dokumen itu sendiri tidak dimasukkan. Fragmen itu sendiri terus ada tetapi sekarang tidak memiliki anak.

Ini memungkinkan Anda untuk memasukkan banyak node ke dalam DOM pada saat yang bersamaan:

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
Tim Down
sumber
3
Terima kasih atas tanggapannya. Anda mengatakan bahwa itu memungkinkan beberapa penyisipan pada saat yang sama tetapi saya dapat mencapainya menggunakan doc.createElement. Satu-satunya perbedaan adalah saya harus membungkus elemen dalam tag <span> terlebih dahulu dan kemudian memasukkan <span> itu ke DOM. Itukah alasan saya harus menggunakan createDocumentFragment? Untuk menghindari elemen yang tidak perlu dimasukkan ke dalam DOM?
screenm0nkey
4
Ya, itu pasti salah satu alasan untuk menggunakannya. Juga, sebuah fragmen dokumen dapat berisi semua jenis node sedangkan elemen mungkin tidak.
Tim Down
3
Sebenarnya fragmen tersebut tidak "menghilang"; browser memindahkan childNodes-nya ke DOM. Jadi fragmen akan tetap ada, tetapi akan kosong setelah penyisipan.
inf3rno
1
@ inf3rno: Oleh karena itu saya menggunakan kata "efektif" dan penjelasan berikutnya, yang hampir sama dengan milik Anda. Saya mengakui bahwa saya seharusnya mengatakan secara eksplisit dalam jawaban bahwa fragmen terus ada tanpa node turunan.
Tim Down
1
@TimDown terima kasih atas jawaban Anda! Jika saya mengerti maksud Anda, berkenaan dengan kinerja, penggunaan, createFragmentdan createElementdalam memori memiliki efek yang kira-kira sama karena keduanya memperbarui DOM secara batch alih-alih memperbarui secara berulang untuk beberapa kali. Meskipun manfaat utamanya createFragmentadalah ia menawarkan Anda fleksibilitas untuk memilih elemen turunan apa pun yang akan ditambahkan secara gratis? Koreksi saya jika saya salah.
Xlee
9

Perbedaan lain yang sangat penting antara membuat elemen dan fragmen dokumen:

Saat Anda membuat elemen dan menambahkannya ke DOM, elemen tersebut ditambahkan ke DOM, serta anak-anak.

Dengan fragmen dokumen, hanya anak-anak yang ditambahkan.

Ambil contoh kasus:

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>

yang menghasilkan format HTML yang salah ini (spasi ditambahkan)

<ul id="ul_test">
  <li>Document Fragment</li>
  <div><li>Inside Div</li></div>
</ul>
Jeremy J Starcher
sumber