2010-01-29 2 views
6

Được quan tâm đến việc xây dựng khối html off-dom trước khi chèn chúng vào dom, tôi đã thực hiện một số thử nghiệm bằng cách sử dụng dynatrace. Tôi đã sử dụng phương pháp của bobince: Is there any way to find an element in a documentFragment?getElementById dựa trên ngữ cảnh chậm hơn 1000 lần so với getElementById gốc. Các công cụ chọn như sizzle có sử dụng chiến lược thông minh hơn không?

Tôi thấy nó chậm hơn gần 1000 lần (trong IE7), điều này làm tôi ngạc nhiên.

Vì chức năng này khá cơ bản, tôi đã tự hỏi về chiến lược được sử dụng bởi các công cụ như sizzle.

Tôi muốn biết liệu có một số cách hiệu quả hơn để thực hiện lựa chọn nút dựa trên ngữ cảnh không?

+0

Bạn không nên thấy nó đáng ngạc nhiên. Ngay lập tức theo mã, anh ta gợi ý rõ ràng là không nên sử dụng nó, "Nó gần như chắc chắn sẽ tốt hơn để theo dõi các tài liệu tham khảo khi bạn đi cùng hơn là dựa vào một chức năng ngây thơ, kém hiệu quả như trên." –

+0

sự bất ngờ là thứ tự hoặc độ lớn: 1000. Tôi mong đợi một cái gì đó giữa 2 và 100. – Olivvv

Trả lời

1

động cơ Khung selector thường được đánh giá phải tay đầu tiên, vì vậy tôi mong chờ một selector ID ngữ cảnh để document.getElementById ID và sau đó kiểm tra xem liệu kết quả là trong context node bằng cách đẩy mạnh các parentNode s. Điều này là khá nhanh, nhưng nó sẽ không hoạt động đối với các cây DOM ngoài tài liệu như ví dụ này. Động cơ chọn sau đó sẽ phải làm điều đó một cách tuyệt vọng chậm, hoặc không quan tâm (ví dụ: Sizzle không hoạt động với DocumentFragment).

Có một cách tốt hơn để nhận ID bên trong một đoạn mà tôi đã nhớ từ đó, đối với các trình duyệt triển khai Selectors-API (IE8, Firefox 3.5, Opera 10, Safari 3.1, Chrome 3). Bạn có thể sử dụng querySelector để áp dụng một selector CSS với DocumentFragment như một nút bối cảnh, như API đòi hỏi DocumentFragment cụ NodeSelector:

alert(frag.querySelector('#myId')) 

Đây không phải là khá nhanh như getElementById, nhưng nó tải tốt hơn so với phiên bản DOM . Không may là hầu hết các framework có tối ưu hóa Selectors-API sẽ không sử dụng chúng trong trường hợp này hay bất kỳ khung nào khác với các nút ngữ cảnh, bởi vì cách mà nút ngữ cảnh hoạt động khác nhau trong querySelector [All] về cách các khung công tác truyền thống triển khai thực hiện nó như thế nào, làm cho chúng không tương thích.

Selectors-API Level 2 đề xuất các phương pháp 'có phạm vi' hoạt động giống như bộ chọn khung truyền thống ... sẽ mất một lúc trước khi có thể sử dụng được, nhưng chúng tôi có thể sẽ không thấy bộ chọn ngữ cảnh được tối ưu hóa trong khung hiện có cho đến lúc đó. Tôi nghĩ rằng đây là một sự xấu hổ, như mặc dù phương pháp querySelector sử dụng nút ngữ cảnh để lọc nhưng không phạm vi không phải là khá tốt, nó vẫn còn khá nhiều có thể sử dụng cho tất cả các trường hợp phổ biến.

+1

Bạn có chắc chắn về 'Element.getElementById'? Toàn bộ tiền đề của lựa chọn theo ngữ cảnh theo id là sai IMHO. Một id là duy nhất trong một bối cảnh 'Document', không phải trong một' Element' hoặc 'DocumentFragment'. –

+0

Ồ vâng. Tôi có vẻ như đang nói dối và suy nghĩ về getElementsByTagName. Rất tiếc! Đang cập nhật ...Tôi đã tìm thấy một số công cụ để chơi với :-) – bobince

+0

Ah. Tôi đã bị sốc rằng tôi có thể đã bỏ lỡ một cái gì đó như Element.getElementById(). Tôi đã đọc một số nội dung về querySelector, nhưng tôi phải tập trung vào IE7. @Cho điểm chính là thực hiện lựa chọn trên html chưa có trong dom. – Olivvv

0

Nếu bạn không nhớ chèn documentFragment của bạn vào DOM tạm ...

function getElementFromFragById(frag, id) { 
    var tempDiv = document.createElement("div"); 
    tempDiv.style.display = "none"; 
    tempDiv.appendChild(frag); 
    document.body.appendChild(tempDiv); 
    var elem = document.getElementById(id); 
    document.body.removeChild(tempDiv); 
    return document.getElementById(id) ? null : elem; //if the element still exists, we have a problem 
} 

này hoạt động đáng tin cậy miễn là bạn documentFragment không chứa các thành phần với id đã tồn tại trong document và bạn muốn tìm kiếm trên id đó.

+0

Tôi muốn thao tác html ra khỏi bản chất để tránh các phản xạ, đó là một chi phí hiệu suất lớn. Thật không may IE7 không reflow khi các yếu tố ẩn bị ảnh hưởng. Xem http://www.phpied.com/the-new-game-show-will-it-reflow/ Trên một lưu ý phụ, tôi không chắc chắn đoạn này vẫn là một mảnh khi đi qua chức năng của bạn, để có thể hủy bỏ hiệu suất đạt được từ việc sử dụng một đoạn. Dù sao tôi m ở đây quan tâm đến hoạt động off-dom, vì vậy không nhất thiết phải mảnh vỡ. – Olivvv