Чи повинен я використовувати document.createDocumentFragment або document.createElement


97

Я читав про фрагменти документа та переробку DOM і дивувався, document.createDocumentFragmentчим відрізнявся від того document.createElement, що, здається, жоден з них не існує в DOM, поки я не додаю їх до елемента DOM.

Я зробив тест (нижче), і всі вони зайняли рівно стільки ж часу (близько 95 мс). Можливо, це могло бути пов’язано з відсутністю стилю, застосованого до будь-якого з елементів, тому, можливо, немає перепланування.

У будь-якому випадку, грунтуючись на прикладі нижче, чому я повинен використовувати createDocumentFragmentзамість того, createElementщоб вставляти в DOM, і яка різниця між ними.

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
Так, це, безумовно, одна з причин використовувати його. Крім того, фрагмент документа може містити будь-який тип вузла, тоді як елемент - ні.
Тім Даун

3
Власне фрагмент не «зникає»; браузер переміщує свої дочірні вузли в DOM. Отже, фрагмент все одно буде існувати, але після вставки він буде порожнім.
inf3rno

1
@ inf3rno: Звідси я вживаю слово "ефективно" та пояснення, яке подається далі, яке майже таке саме, як і ваше. Я визнаю, що я повинен був прямо сказати у відповіді, що фрагмент продовжує існувати без дочірніх вузлів.
Тім Даун

1
@TimDown дякую за вашу відповідь! Якщо я правильно зрозумів, що стосується продуктивності, використання createFragmentта createElementв пам'яті, це приблизно такий самий ефект, як вони обидва пакетно оновлювали DOM замість ітеративного оновлення кілька разів. Хоча головною перевагою createFragmentє те, що він пропонує вам гнучкість у виборі будь-яких дочірніх елементів, які потрібно додати безкоштовно? Виправте мене, якщо я помилявся.
Xlee

9

Ще одна дуже важлива відмінність між створенням елемента та фрагментом документа:

Коли ви створюєте елемент і додаєте його до 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>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.