2009-04-03 44 views
6

Tôi đang điều chỉnh hiệu suất mã của mình và ngạc nhiên khi thấy rằng nút cổ chai không phải là chèn nút dom, mà là lựa chọn.Cách nhanh nhất để lấy phần tử dom là gì?

Đây là nhanh:

var row = jquery(rowHTML).appendTo(oThis.parentTable); 

nhưng sau đó nhận được của một phần tử bên trong "hàng" được chậm:

var checkbox = jquery(".checkbox input", row); 

tôi cần phải nhận được vào hộp kiểm trong mỗi hàng vì vậy tôi có thể đính kèm một xử lý sự kiện cho nó. Chọn hộp kiểm là ALMOST 10X AS SLOW khi chèn toàn bộ hàng chính.

Tôi đang làm gì sai ở đây?

+0

ummm. này là số lẻ. Hai người đã cho tôi một giải pháp làm việc, nhưng sau đó bài viết của họ biến mất. Dù sao, có vẻ như việc loại bỏ các tên lớp từ các bộ chọn sẽ tăng tốc độ lên rất nhiều thứ. Câu trả lời của Christoph, để sử dụng sự kiện phái đoàn thực sự có vẻ tốt nhất với tôi, nhưng là một sự thay đổi lớn hơn. – morgancodes

Trả lời

1

Thử đặt tên lớp trên trường nhập. Điều đó có thể chứng minh là nhanh hơn.

Lý do là mã của bạn đi qua tất cả các lớp .checkbox, cố gắng tìm con đầu vào của phần tử đó và trả về điều đó. Tôi nghĩ rằng hành động đó có thể là thủ phạm của bạn.

Chỉ đơn giản là tìm kiếm tất cả các phần tử có lớp đầu vào có, bạn có thể thấy một số tăng tốc.

2
var checkbox = jquery(".checkbox input", row); 

Thao tác này sẽ vượt qua toàn bộ cây dom để tìm hộp kiểm. Bạn có thể tăng tốc nó bằng cách thay đổi bộ chọn thành một ID có thể sử dụng chức năng getElementById của trình duyệt gốc.

var checkbox = jquery("#checkbox input", row); 

Bạn cũng có thể sử dụng hàng làm điểm bắt đầu cho tìm kiếm DOM như ví dụ sau. Bây giờ, bạn không phân tích cú pháp thông qua toàn bộ cây DOM để tìm phần tử phù hợp.

var row = jquery(rowHTML).appendTo(oThis.parentTable); 
row.children(".checkbox input"); 
+0

re: duyệt qua toàn bộ cây DOM - không phải điều này chỉ duyệt qua các nút con của "hàng" không? – annakata

+0

Tôi nghĩ rằng việc thêm đối số thứ hai, "hàng" sẽ ngăn jquery đi qua toàn bộ cây dom, và làm cho nó bắt đầu chỉ với phần tử hàng của tôi. Tôi có nhầm không? – morgancodes

+0

Hmmm, bạn sẽ làm một số thử nghiệm. Bạn có chủ yếu sử dụng các hàng bảng hoặc div không? – jfar

1

Hãy thử sử dụng Sly, chú trọng đến hiệu suất.

2

Sử dụng ủy quyền sự kiện và thêm một trình xử lý duy nhất vào phần tử gốc chứ không phải chính hộp kiểm.

jQuery hỗ trợ điều này thông qua chức năng live().

+0

Ý tưởng tuyệt vời. Nó chưa bao giờ xảy ra với tôi để tiếp cận sự kiện xử lý theo cách này. – morgancodes

+0

@morgancodes: Tôi bắt đầu sử dụng sự kiện ủy quyền gần như dành riêng cho sự kiện bubbling và thêm hầu hết người nghe vào tài liệu (gốc của phân cấp sự kiện); nó có thể không hiệu quả (tất cả mọi người nghe đều không phụ thuộc vào nguồn sự kiện), nhưng nó cực kỳ tiện lợi, ví dụ như không cần hack hacking – Christoph

0

Nếu bạn đang tìm kiếm hiệu suất, bộ chọn jQuery rất chậm. Trong ví dụ ở đó, nó phải quét toàn bộ cây DOM và kiểm tra các lớp CSS và cứ thế để tìm các nút có liên quan.

Nhanh hơn đáng kể để sử dụng các phương pháp DOM gốc. Có một số so sánh hiệu suất thư viện thú vị ở đây:

http://ajaxian.com/archives/taskspeed-more-benchmarks-for-the-libraries-and-browsers

13

DOM thao tác sử dụng các chức năng có nguồn gốc từ thực hiện các hoạt động đơn giản. Các nhà cung cấp trình duyệt tối ưu hóa chúng. Bạn đang xây dựng hàng từ HTML. Nội bộ jQuery đang sử dụng .innerHTML để xây dựng bộ sưu tập mà sau đó các bản vá lỗi vào trình phân tích cú pháp siêu nhanh của trình duyệt.

Lựa chọn chậm so với mã JS cần lặp lại DOM nhiều lần. Các trình duyệt mới hơn có xử lý lựa chọn gốc cung cấp các tăng tốc đáng kể cho JS dựa trên bộ chọn. Khi thời gian di chuyển trên điều này sẽ ít hơn của một vấn đề.

Sau đây là cách truy vấn trong câu hỏi, $(".checkbox input", row), phá vỡ:

  1. row.getElementsByTagName('*');
  2. cho vòng qua mọi phần tử trở lại (tất cả các yếu tố trong hàng) và thử nghiệm elements[i].className với /(\s|^)checkbox(\s|$)/.
  3. cho mỗi vòng lặp vẫn còn lại và thu thập matched[i].getElementsByTagName('input');
  4. duy nhất bộ sưu tập cuối cùng.

Điều này khác với jQuery 1.3 vì động cơ của nó di chuyển qua bộ chọn theo cách khác, bắt đầu với nhận tất cả các yếu tố đầu vào và sau đó thử nghiệm các phần tử gốc.

Hãy nhớ rằng các công cụ chọn JS thực hiện nhiều thông số kỹ thuật chọn CSS hơn là thực sự có thể sử dụng với CSS (hoặc được thực hiện bởi trình duyệt hiện tại). Khai thác này, và kiến ​​thức về các công cụ, chúng ta có thể tối ưu hóa bộ chọn có thể được tối ưu hóa trong một vài cách khác nhau:

Nếu bạn biết những gì yếu tố gõ .checkbox là:

$("td.checkbox input", row); 

Nó là nhanh hơn cho bộ lọc đầu tiên cho loại và sau đó cho lớp chỉ cho những trận đấu đó. Điều này không áp dụng cho một tập hợp con các phần tử rất nhỏ, nhưng điều đó gần như không bao giờ xảy ra ở dạng praxis.

Kiểm tra lớp đơn là chậm nhất trong số selectors people actually use phổ biến nhất.

lựa chọn đơn giản hơn:

$("input[type=checkbox]", row); 

Một vòng lặp là nhanh hơn so với hai vòng. Điều này chỉ tìm thấy các yếu tố đầu vào và sau đó trực tiếp lọc chúng theo thuộc tính type. Vì các phần tử con/con không bao giờ được sử dụng, độc đáo cũng có thể bị bỏ qua (và các công cụ thông minh sẽ cố gắng làm điều này vì duy nhất là chậm).

Một bộ chọn trực tiếp hơn:

$("td:first.checkbox input", row); 

Một bộ chọn phức tạp hơn thực tế có thể nhanh hơn nếu nó là trực tiếp hơn (YMMV).

Nếu có thể, di chuyển bối cảnh tìm kiếm lên đến mức bảng:

Bằng cách này, tôi có nghĩa là thay vì lặp qua các hàng, và tìm kiếm các hộp kiểm trong mỗi người, để họ một mình cho đến sau lặp lại và sau đó chọn tất cả chúng tại một thời điểm:

$("tr td:first.checkbox input", table); 

Điểm này là loại bỏ chi phí để kích hoạt công cụ chọn lên nhiều lần, nhưng thay vào đó làm mọi thứ trong một đoạn. Điều này được trình bày ở đây cho đầy đủ hơn là một cái gì đó mà tôi nghĩ rằng sẽ trả về tốc độ lớn.

Đừng chọn:

Build hàng từ bit, gán các sự kiện như bạn đi.

var row = $('<tr></tr>'); 
var cell = $('<td class="checkbox"></td>').appendTo(row); 
$('<input type="checkbox" name="..."/>').appendTo(cell).click(/* ... */); 

Điều này có thể là không thể vì lý do Ajax hoặc các mẫu khác ngoài tầm kiểm soát của bạn. Ngoài ra, tốc độ có thể không đáng để biến mã của bạn thành loại lộn xộn này, nhưng đôi khi điều này có thể có ý nghĩa.

Hoặc nếu không có cách nào phù hợp với bạn hoặc trả lại hiệu suất quá, thì có thể đã đến lúc phải suy nghĩ lại toàn bộ phương pháp. Bạn có thể gán một event listener cao lên cây và lấy những sự kiện đó, thay vì dụ mỗi phần tử:

$('table').change(function(e){ 
    // you may want a faster check... 
    if ($(e.target).is('input[type=checkbox]')) { 
    // do some stuff ... 
    } 
}); 

Bằng cách này bạn không làm bất cứ điều gì trừ khi và cho đến khi, người dùng thực sự yêu cầu nó. Nhanh nhất. :-)

+0

wow. câu trả lời dài, tuyệt vời. Tôi sẽ cần một phút để tiêu hóa điều này. Cảm ơn Borgar! – morgancodes

+0

Tôi tình cờ đã viết một công cụ chọn để đây là một lĩnh vực mà tôi tình cờ biết một vài điều về. :-) – Borgar

+0

Cảm ơn bạn đã giải thích sâu –

0

Cách nhanh nhất để có được phần tử DOM là sử dụng JavaScript thuần túy và gọi nó bằng ID.

var element = document.getElementById('element); 
Các vấn đề liên quan