ฉันควรใช้ document.createDocumentFragment หรือ document.createElement


97

ฉันกำลังอ่านเกี่ยวกับส่วนของเอกสารและการจัดเรียง DOM และสงสัยว่าdocument.createDocumentFragmentแตกต่างจากdocument.createElementที่ดูเหมือนว่าไม่มีอยู่ใน DOM จนกว่าฉันจะผนวกเข้ากับองค์ประกอบ DOM

ฉันทำการทดสอบ (ด้านล่าง) และทั้งหมดใช้เวลาเท่ากันทุกประการ (ประมาณ 95ms) เดาได้ว่าอาจเป็นเพราะไม่มีสไตล์ที่ใช้กับองค์ประกอบใด ๆ ดังนั้นจึงอาจไม่มีการแสดงซ้ำ

อย่างไรก็ตามตามตัวอย่างด้านล่างเหตุใดฉันจึงควรใช้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');

คำตอบ:


99

ความแตกต่างคือส่วนของเอกสารจะหายไปอย่างมีประสิทธิภาพเมื่อคุณเพิ่มลงใน 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
ใช่นั่นเป็นเหตุผลหนึ่งที่ต้องใช้อย่างแน่นอน นอกจากนี้ส่วนของเอกสารอาจมีโหนดชนิดใดก็ได้ในขณะที่องค์ประกอบต้องไม่มี
Tim Down

3
จริงๆแล้วชิ้นส่วนไม่ได้ "หายไป"; เบราว์เซอร์จะย้ายโหนดลูกไปที่ DOM ดังนั้นส่วนจะยังคงมีอยู่ แต่จะว่างเปล่าหลังจากการแทรก
inf3rno

2
@ inf3rno: ดังนั้นฉันจึงใช้คำว่า "ได้ผล" และคำอธิบายที่ตามมาซึ่งเหมือนกับของคุณมาก ฉันยอมรับว่าฉันควรจะพูดอย่างชัดเจนในคำตอบที่ว่าชิ้นส่วนยังคงมีอยู่โดยไม่มีโหนดลูก
Tim Down

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>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.