2010-08-03 22 views
72

Tôi đã reading about document fragments và DOM reflow và tự hỏi làm thế nào document.createDocumentFragment khác với document.createElement vì có vẻ như không tồn tại trong DOM cho đến khi tôi thêm chúng vào phần tử DOM.Tôi có thể sử dụng document.createDocumentFragment hoặc document.createElement

Tôi đã làm một thử nghiệm (bên dưới) và tất cả chúng đều chính xác cùng một lượng thời gian (khoảng 95ms). Tại một đoán này có thể có thể là do không có phong cách áp dụng cho bất kỳ các yếu tố, do đó, không có reflow có thể.

Dù sao, dựa trên ví dụ bên dưới, tại sao tôi nên sử dụng createDocumentFragment thay vì createElement khi chèn vào DOM và sự khác biệt giữa hai.

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'); 
+3

này nghe có vẻ như một công việc cho jsperf. Vâng? Không? – Nenotlep

Trả lời

75

Sự khác biệt là đoạn tài liệu sẽ biến mất khi bạn thêm nó vào DOM. Điều xảy ra là tất cả các nút con của đoạn tài liệu được chèn vào vị trí trong DOM nơi bạn chèn đoạn tài liệu và bản thân đoạn tài liệu không được chèn vào. Bản thân mảnh vỡ vẫn tiếp tục tồn tại nhưng bây giờ không có con.

này cho phép bạn chèn nhiều nút vào DOM cùng một lúc:

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

Cảm ơn bạn đã phản hồi. Bạn nói rằng nó cho phép chèn nhiều cùng một lúc nhưng tôi có thể đạt được điều đó bằng cách sử dụng doc.createElement. Sự khác biệt duy nhất là tôi đã phải bọc các phần tử trong một thẻ trước và sau đó chèn vào DOM. Đó có phải là lý do tôi nên sử dụng createDocumentFragment không? Để tránh các phần tử không cần thiết được chèn vào DOM? – screenm0nkey

+3

Vâng, đó chắc chắn là một lý do để sử dụng nó. Ngoài ra, một đoạn tài liệu có thể chứa bất kỳ loại nút nào trong khi một phần tử có thể không. –

+3

Thực ra đoạn không "biến mất"; trình duyệt di chuyển các ChildNodes của nó sang DOM. Vì vậy, đoạn sẽ vẫn tồn tại, nhưng nó sẽ trống rỗng sau khi chèn. – inf3rno

4

Một sự khác biệt rất quan trọng giữa việc tạo ra một phần tử và một đoạn tài liệu:

Khi bạn tạo một yếu tố và thêm nó vào DOM, phần tử được nối vào DOM, cũng như các phần tử con.

Với đoạn tài liệu, chỉ có trẻ em được nối.

Lấy trường hợp của:

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>

mà kết quả trong HTML bị thay đổi này (khoảng trắng thêm)

<ul id="ul_test"> 
    <li>Document Fragment</li> 
    <div><li>Inside Div</li></div> 
</ul> 
Các vấn đề liên quan