2012-12-13 13 views
7

Tôi đã xem xét việc sử dụng documentFragments trong ứng dụng Backbone.js và tự hỏi tại sao tôi thấy các ví dụ trong đó "cloneNode" được sử dụng khi chắp thêm documentFragment vào phần tử DOM mẹ.Tại sao cloneNode cần được sử dụng khi thêm một tài liệuFragment?

Có thể xem ví dụ here. Nếu bạn nhìn xuống phần DocumentFragment bạn sẽ thấy điều này:

oFrag = document.createDocumentFragment(); 
for (var i = 0, imax = aElms.length; i < imax; i++) { 
oFrag.appendChild(aElms[i]); 
} 

o.innerHTML = ''; 
o.appendChild(oFrag.cloneNode(true)); 

Tại sao "oFrag" được sao chép thay vì chỉ thêm nó? Một blog post không sử dụng "cloneNode" (làm so sánh).

+0

+1, rất thú vị thực sự. Đoán duy nhất của tôi (và khá hoang dã) là việc sử dụng 'cloneNode' cho phép chúng ta kiểm soát tốt hơn phạm vi' oFrag'. – raina77ow

+0

Tôi không nghĩ rằng điều này xứng đáng được giả mạo thành một câu trả lời đầy đủ, nhưng dù sao ... Đơn giản bằng cách tìm kiếm 'documentFragment cloneNode' Tôi đã tìm thấy [bài đăng này] (http://ejohn.org/blog/dom- documentfragments /) của John Resig.) Trong chủ đề của bài viết này, một loạt các nút sẽ được chèn vào DOM _several_ lần, do đó nhân bản documentFragment thực sự là một lựa chọn tốt hơn. – raina77ow

Trả lời

5

first link bạn nói đến các blog post nơi autor sử dụng document.getElementsByTagName thay vì document.getElementById, như trong trường hợp thử nghiệm. Nếu bạn muốn có một nhiều yếu tố (cụ thể là: divs) được đưa ra cùng documentFragment, bạn phải sao chép nó:

Nếu con là một tham chiếu đến một nút hiện có trong tài liệu, appendChild di chuyển nó từ vị trí hiện tại của mình để vị trí mới (nghĩa là không có yêu cầu xóa nút khỏi nút cha của nó trước khi thêm nó vào một nút khác).

Điều này cũng có nghĩa là một nút không thể ở hai điểm của tài liệu cùng một lúc. Vì vậy, nếu nút đã có một phụ huynh, nó là lần đầu tiên loại bỏ, sau đó nối vào vị trí mới.

qua MDN

Nhiều khả năng các tác giả (hoặc người khác) sao chép-dán mã mà không cần dùng này vào xem xét. Hãy tự thử - bạn có thể sử dụng appendChild mà không cần cloneNode và mọi thứ đều hoạt động tốt. Một khả năng khác là ai đó đã tạo ra trường hợp thử nghiệm này trên jsperf không nhận được nhiều mã chuẩn bị hoạt động như thế nào và lo lắng rằng thử nghiệm đầu tiên sẽ trống rỗng aElms mảng và nó sẽ không hoạt động nữa. In fact mã chuẩn bị được thực hiện trước mỗi lần lặp thời gian, do đó không cần phải lo lắng về nội dung của nó.

Điều cuối cùng có thể là mối quan tâm về hiệu suất. Nếu bạn thực sự muốn thử nghiệm chèn thực, bạn cần sao chép nút. Nếu không, bạn sẽ kiểm tra cây reattachment thay vào đó (xem liên kết MDN ở trên).

Cũng xin lưu ý rằng cloning destroys event listeners.

Chúc mừng fragmentin '! ;)

2

Tôi không chắc chắn, nhưng trong ngữ cảnh của liên kết bạn cung cấp (kiểm tra hiệu suất) oFrag.cloneNode(true) có thể là một biện pháp bảo vệ chống lại việc sử dụng lại các phần tử đã được thêm vào DOM trong các lần chạy trước đó. thi công nhanh hơn.

Tôi không thấy lý do nào để sử dụng nó trong các trường hợp sử dụng thông thường của documentFragments.

+0

+1 Tôi cho rằng đó là lý do thực sự. – raina77ow

0

Tôi không nghĩ điều đó là cần thiết. Tôi đoán nó chỉ được sử dụng để tách aElms khỏi bị tham chiếu tĩnh, nơi họ sẽ cần phải được loại bỏ khỏi cha mẹ trước đây của họ khi gọi appendChild. Nó chỉ cho hiệu suất trong thử nghiệm này.

Tuy nhiên, đoạn mã sau (tương tự như các bài kiểm tra appendChild) sẽ có ý nghĩa hơn đối với tôi:

var oFrag = document.createDocumentFragment(); 
for (var i = 0, imax = aElms.length; i < imax; i++) 
    oFrag.appendChild(aElms[i].cloneNode(true)); 
// using it here:    ^^^^^^^^^^^^^^^^ 
o.appendChild(oFrag); 

Mặc dù nó có thể là chậm hơn so với gọi đó là một lần duy nhất trên toàn bộ đoạn, nơi cây nút được đệ quy bằng mã gốc.

Ngoài ra kiểm tra http://jsperf.com/cloning-fragments :-)

2

Nếu bạn chắp thêm một tài liệuPhân tích cho một phần tử, và sau đó bạn xóa các nút được thêm vào khỏi phần tử đó, tài liệu của bạnPhân tích cũng sẽ trống và không thể sử dụng lại được nữa! Thêm một bản sao của documentFragment của bạn ngăn chặn điều này và cho phép nhiều reuses của documentFragment của bạn.

Tôi giả sử tác giả của đoạn mã jsperf đang thử nghiệm cho một trường hợp như vậy.

Ví dụ: danh sách thả xuống có mối quan hệ cha-con. Giả sử bạn có danh sách thả xuống nơi bạn chọn lục địa và danh sách thả xuống thứ hai liệt kê tất cả các quốc gia trong lục địa đó. Nếu bạn muốn cache các documentFragments đã tạo với các nút tùy chọn sau khi tạo, sử dụng cloneNode là cần thiết. Hãy tưởng tượng một người nào đó chọn châu Âu, sau đó châu Phi, sau đó châu Âu một lần nữa: bạn có thể tạo lại toàn bộ documentfragment, bộ nhớ cache nó.

Tôi tạo ra một đoạn jsperf để minh họa sự khác biệt thực hiện tái tạo lại documentFragments vs bộ nhớ đệm và nhân bản các mảnh vỡ:

http://jsperf.com/documentfragment-cache-vs-recreate

+0

cảm ơn thông tin, nó khá thú vị. – codecraig

Các vấn đề liên quan