2010-02-21 42 views
43

Câu hỏi đặt ra là, so sánh ghép bằng cách sử dụng innerHTML và nối thêm một nút văn bản vào nút hiện có. Điều gì đang xảy ra đằng sau hiện trường?"innerHTML + = ..." vs "appendChild (txtNode)"

những suy nghĩ của tôi xung quanh này cho đến nay:

  • Tôi đoán cả hai đều gây ra một 'reflow'.
  • Sau này (thêm một nút văn bản), từ những gì tôi biết, cũng gây dựng lại hoàn toàn DOM (đúng không? Cả hai đều làm điều này?).
  • Trước đây dường như có một số tác dụng phụ khó chịu khác, như gây ra các tham chiếu đã lưu trước đó cho các nút con tới nút tôi đang sửa đổi innerHTML, không còn trỏ đến 'DOM hiện tại'/'phiên bản chính xác của nút con' . Ngược lại, khi phụ thêm trẻ em, tham chiếu dường như vẫn nguyên vẹn. Tại sao điều này?

Tôi hy vọng mọi người có thể xóa điều này cho tôi, cảm ơn!

Trả lời

69

Sau đó (appendChild) không không gây dựng lại hoàn toàn DOM hoặc thậm chí tất cả các phần tử/nút trong mục tiêu.

Trước đây (thiết lập innerHTML) không gây dựng lại hoàn toàn nội dung của phần tử đích, nếu bạn đang phụ thêm là không cần thiết.

Gắn thêm qua innerHTML += content làm cho trình duyệt chạy qua tất cả các nút trong phần tử tạo chuỗi HTML để cung cấp cho lớp JavaScript. Mã của bạn sau đó nối văn bản vào nó và đặt innerHTML, khiến trình duyệt thả tất cả các nút cũ trong mục tiêu, phân tích lại tất cả các HTML đó và tạo các nút mới. Vì vậy, theo nghĩa đó, nó có thể không hiệu quả. (Tuy nhiên, phân tích cú pháp HTML là gì các trình duyệt làm và họ đang thực sự, thực sự nhanh vào nó.)

Thiết innerHTML không thực sự vô hiệu bất kỳ tham chiếu đến các yếu tố bên trong phần tử mục tiêu mà bạn có thể được tổ chức - vì những yếu tố don Không tồn tại nữa, bạn đã xóa chúng và sau đó đặt chúng vào cái mới (trông rất giống) khi bạn đặt innerHTML.

Tóm lại, nếu bạn đang nối, tôi muốn sử dụng appendChild (hoặc insertAdjacentHTML, xem bên dưới). Nếu bạn đang thay thế, có những tình huống rất hợp lệ khi sử dụng innerHTML là một lựa chọn tốt hơn là tự tạo cây thông qua API DOM (tốc độ là trưởng trong số đó).

Cuối cùng, điều đáng nói đến là insertAdjacentHTML, là một hàm mà bạn có thể sử dụng để chèn các nút và phần tử vào hoặc bên cạnh phần tử bằng chuỗi HTML. Bạn có thể gắn thêm vào một phần tử với nó: theElement.insertAdjacentHTML("beforeend", "the HTML goes here"); Đối số đầu tiên là nơi đặt HTML; lựa chọn của bạn là "beforebegin" (bên ngoài phần tử, ngay phía trước nó), "afterbegin" (bên trong phần tử, lúc đầu), "beforeend" (bên trong phần tử, ở cuối) và "afterend" (bên ngoài phần tử, chỉ sau nó) . Lưu ý rằng "afterbegin""beforeend" chèn vào chính phần tử, trong khi "beforebegin""afterend" chèn vào phần tử của phần tử của phần tử đó. Được hỗ trợ bởi tất cả các trình duyệt máy tính để bàn lớn, tôi không có ý tưởng hỗ trợ điện thoại di động tốt (mặc dù tôi chắc chắn iOS Safari và Android 2.x và lên có nó, ít nhất), nhưng the shim là nhỏ.

+0

@TK: Làm thế nào về hỗ trợ trình duyệt? Một kỹ thuật có nhiều khả năng hơn người khác để làm việc trên các trình duyệt cũ hơn và/hoặc di động không? – skaffman

+6

@skaffman: Trong ngày và tuổi này, tôi mong đợi cả hai sẽ có sẵn trong bất kỳ trình duyệt nào bạn đang làm việc cùng. 'innerHTML' không chuẩn nhưng hầu như được hỗ trợ phổ biến (để cung cấp cho bạn một ý tưởng, cả Prototype lẫn jQuery đều dựa vào nó). 'appendChild' là một phần của thế hệ DOM cũ nhất, nó sẽ có mặt ở đó. :-) Lưu ý rằng có giới hạn và quirks với 'innerHTML'. Bạn không thể thay thế một hàng của bảng bằng cách đặt ví dụ 'innerHTML' của phần tử TR trên một số trình duyệt. IE sẽ loại bỏ whitepace hàng đầu khi bạn sử dụng nó. Các yếu tố hình thức có thể là một thách thức. Vv –

+3

+1 từ tôi :-) Tôi sẽ nói nếu bạn đang sử dụng 'innerHTML', không sử dụng nó trong vòng lặp. Nó rất không hiệu quả để làm như vậy bởi vì bạn đang bắt đầu phân tích cú pháp nhiều lần. Tôi đã nhìn thấy các vòng như 'for (var i = 0; i