2012-03-08 37 views
28

Tôi có nhiều yếu tố mà một trong các tiện ích JS của tôi cần tạo và thêm vào DOM thường xuyên. Họ không bao giờ thay đổi.Cách tốt nhất để tạo các phần tử DOM tĩnh lớn trong JavaScript là gì?

Vì vậy, một lựa chọn sẽ được lưu trữ HTML chính nó như là một chuỗi trong JS và sử dụng JQuery để tạo ra các yếu tố từ chuỗi, sau đó nối nó vào tài liệu:

var elements = "<div><table><tr><td>1</td><td>2</td></tr></table></div>"; 
function create() { 
    return $(elements); 
} 
$("body").append(create()); 

Một lựa chọn khác là để viết một chức năng đó sẽ sử dụng document.createElement ("div"), hoặc $ ("div < >") nhiều lần để xây dựng các yếu tố, gắn chúng với nhau khi cần thiết, sau đó nối đến tài liệu:

function create() { 
    return $("<div>").append($("<table>")...... 
} 
$("body").append(create()); 

Trong trường hợp đầu tiên, tôi có một chuỗi JS lớn thực sự là HTML. Trong trường hợp thứ hai, tôi có một đoạn JS khó sử dụng thực sự đại diện cho HTML.

Có (dis) lợi thế nào cho cái này hay cách khác không? Có một giải pháp tốt hơn tôi không nghĩ đến?

+1

này nghe có vẻ giống như một công việc cho một công cụ khuôn mẫu JS, chẳng hạn như http: // handlebarsjs Tôi không biết đủ về nó để cung cấp cho bạn một giải pháp thực sự, nhưng tôi nghĩ rằng nó có thể giúp đỡ. – Nix

+0

@Nix Cảm ơn, đã vấp phải điều này trong khi tìm cách tạo các phần tử DOM phức tạp theo cách thức lành mạnh và có thể duy trì được. handlebars.js là chính xác những gì tôi cần. :) – DavidScherer

Trả lời

27

Lưu ý: Nếu bạn ghét đọc, chỉ cần kiểm tra tóm tắt bên dưới để có câu trả lời cuối cùng

Có thể bạn không thực sự cần tạo những người có trợ giúp o f jQuery.

Nếu cấu trúc của html đó phức tạp (do đó sử dụng phương pháp document.createElement sẽ là quá mức cần thiết), tôi sẽ đi với thuộc tính innerHTML.

// somewhere in your code, preferably outside of global scope 
var div = document.createElement('div') 
div.id = 'mycustomdiv' 
document.getElementsByTagName('body')[0].appendChild(div); 
// assuming elements contains string of html with your elements 
div.innerHTML = elements; 

Bằng cách đó bạn tránh chi phí không cần thiết (tạo ra) một lần nữa để tạo và gói các phần tử trong đối tượng jQuery.


Cập nhật: kiểm tra cho mình những phương pháp nhanh nhất http://jsperf.com/creating-complex-elements là những gì. Kiểm tra này xác nhận rằng khi bạn đang cố gắng ép từng bit cuối cùng của hiệu suất trở lại vani javascript và các hoạt động DOM cổ điển.


Cập nhật 2. Tổ chức điều tra tại sao innerHTML phương pháp trên Firefox 10 có kết quả xấu ví dụ liên quan đến truyền đầy đủ chuỗi jQuery.append, tôi đã xem xét các nguồn jQuery.

Khi nó quay ra (trong jQuery 1.7.1), họ đang sử dụng một cách khác để tạo ra các phần tử dom bằng cách sử dụng document.createDocumentFragment (với một số dự phòng cho các trình duyệt không có hỗ trợ thích hợp).

DocumentFragments là các nút DOM. Chúng không bao giờ là một phần của cây DOM chính. Trường hợp sử dụng thông thường là tạo phân đoạn tài liệu, chắp thêm các phần tử vào đoạn tài liệu và sau đó chắp thêm đoạn tài liệu vào cây DOM. Trong cây DOM, mảnh tài liệu được thay thế bởi tất cả các con của nó.

Kể từ khi đoạn tài liệu là trong bộ nhớ và không nằm trong cây DOM chính, phụ thêm con để nó không gây trang reflow.

Giả sử createDocumentFragment có sẵn, đây là cách tiếp cận tốt nhất về hiệu suất tổng thể của trình duyệt.

Vì vậy, để tổng hợp:

Tôi đã sửa. Nếu bạn đang tìm kiếm hiệu suất tốt nhất trên các trình duyệt khác nhau khi tạo các phần tử DOM mới, hãy tập trung vào các đoạn tài liệu (sử dụng jQuery nếu bạn không muốn tự xử lý các trường hợp góc khác nhau).

Để biết thêm đọc liên quan đến documentFragment kiểm tra bài này trên blog của John Resig http://ejohn.org/blog/dom-documentfragments/

+0

+1 cho bản tóm tắt ở cuối. Tôi nghĩ bạn nên in đậm và chỉ điều đó. – styfle

+0

@WTK, tôi nghĩ thử nghiệm sẽ chỉ công bằng nếu nó xóa trẻ sau mỗi 25 lần chèn, bởi vì khi đạt được thử nghiệm cuối cùng DOM bị ô nhiễm nặng nề và trình duyệt đang khóc. –

+0

Có thể một cái gì đó như thế này http://jsperf.com/dquery-vs-jquery-inserting-dom-elements –

2

Bạn có thể thử thực hiện tìm nạp AJAX của khối HTML tĩnh thay vì lưu trữ nó trong chính trang đó. Nó cho phép bạn linh hoạt hơn với loại khối bạn muốn chèn trong tương lai.

Cách khác (đây chỉ là một ý tưởng ngẫu nhiên và không được tô đậm), bạn có thể lưu trữ "cấu trúc" dưới dạng dữ liệu JSON và sau đó phân tích động nó. Có thể là một cái gì đó như {"div": {"div": {"span": "Text here"}}} cho <div><div><span>Text here</span></div></div>. Tôi vẫn đi với AJAX mặc dù. :)

+0

Đã không nghĩ đến việc lưu trữ nó trên máy chủ ... Tôi cho rằng tôi có thể tạo một đoạn JSP cho nó và truy xuất nó bằng AJAX. Hmm .. –

1

Nếu bạn đang tìm kiếm hiệu suất, tôi sẽ gắn liền với phiên bản đầu tiên vì bạn đang gọi số $('<div>') hoặc $('<table>') bạn đang tạo đối tượng jQuery mới và sau đó gọi .append().
Tôi sẽ đi với người đầu tiên.

+0

Nhưng nhanh hơn việc cho phép JQuery phân tích cú pháp một chuỗi lớn? Tôi tưởng tượng rằng có thể là tốn kém quá ... –

+0

Vâng tôi không chắc chắn, Nó phụ thuộc vào bao nhiêu yếu tố bạn muốn tạo! Nhưng làm việc với ajax sẽ không phải là một ý tưởng tốt, bởi vì điều đó sẽ làm chậm nó xuống nhanh hơn. Nhưng tại sao bạn lại trả về một đối tượng jquery trong hàm đó? trả về chuỗi và nó cũng sẽ hoạt động! –

1

Bạn đã tự trả lời.

CHỈNH SỬA: mẫu đã xóa sai.

Hoặc có một tùy chọn, bạn có thể đặt mã HTML ngay vào html hiện bên trong div ẩn như thế này:

<div id="hiddenContainer" style="display:none;"> 
    <div><table><tr><td>1</td><td>2</td></tr></table></div> 
</div> 

Và sau đó trong jquery, bạn có thể đọc nó:

var elements = $("#hiddenContainer").html() 
+0

Không có chuỗi đa dòng (thích hợp) nào trong JS. – Flo

+0

@Flo bạn có thể xây dựng trên đó không? Hoặc liên kết? –

+0

http://jsfiddle.net/AzPvy/2/ – Flo

22

Phân tích chi tiết của 3 commons cách tạo DOM trong JS và phương pháp tốt nhất.

Tôi sẽ cung cấp 3 cách để tạo DOM lớn và ưu điểm và nhược điểm của chúng, và tất nhiên là cách tối ưu nhất để tạo DOM lớn và tại sao. Điểm mấu chốt là khi tạo DOM trong js, các phương thức JS và DOM gốc là bạn của bạn, không sử dụng Jquery trừ khi không có cách nào khác (điều này không chắc chắn).

Kiểm tra dữ liệu để so sánh: Đã tạo 400 hàng với 5 cột và được nối vào DOM. testData là danh sách các đối tượng mà bạn nhận được từ chương trình phụ trợ dưới dạng json để tạo bảng.

đính kèm Execution time kết quả kiểm tra ảnh chụp cho các trình duyệt khác nhau enter image description here HTML

<div id="employeeListContainer1"></div> 
<table id="employeeList2"> 
<thead> 
    <tr> 
     <th>First Name</th> 
     <th>Last Name</th> 
     <th>Title</th> 
     <th>ID</th> 
     <th>Department</th> 
    </tr> 
</thead> 

cách 1: String nối (Tối ưu hóa Hầu hết cách về hiệu suất trên các trình duyệt)

var tableElementContainer1 = document.getElementById("employeeListContainer1"), 
    temptableHolder = '<table><thead><tr><th>First Name</th><th>Last Name</th><th>Title</th><th>ID</th><th>Department</th></tr></thead><tbody>'; 
     for(var i=0,len=testData.length; i<len; i++){ 
       temptableHolder += '<tr><td>' + testData[i].firstName + '</td><td>' + testData[i].lastName + '</td><td>' + testData[i].title 
         + '</td><td>' + testData[i].id + '</td><td>' + testData[i].department + '</td></tr>'; 
      } 
    temptableHolder += '</tbody></table>'; 
    tableElementContainer1.innerHTML = temptableHolder ; 

Ưu điểm: - Thời gian thực hiện nhanh nhất trên Firefox/Chrome/IE/Safari (3-5 millisec trên các trình duyệt). Được đo lường thông qua cả API performance.now() và console.time().

Nhược điểm: - Khi số lượng cột nhiều hơn và bạn cần phải đặt nhiều thuộc tính thì làm việc với chuỗi có thể khó khăn và ít khó chịu hơn.

Cách 2: Native Js document.createElement() (Đây là cách tiếp cận tốt nhất 2 về hiệu suất trên các trình duyệt)

var tableBody = document.createElement('tbody'), 
tableElement2 = document.getElementById("employeeList2"), 
    for(var i=0,len=testData.length; i<len; i++){ 
      tableRow = document.createElement("tr"); 
      for(var k in testData[i]){ 
       rowCell = document.createElement("td"); 
       rowCell.appendChild(document.createTextNode(testData[i][k])); 
       tableRow.appendChild(rowCell); 
      } 
      tableBody.appendChild(tableRow); 
     } 
tableElement2.appendChild(tableBody); 

Ưu điểm: - 2nd thời gian thực hiện nhanh nhất trên trình duyệt Firefox/Chrome/Safari (5 đến 12 millisec trên các trình duyệt). Được đo lường thông qua cả API performance.now() và console.time(). - Nhiều chính tenable hơn cách tiếp cận 1st

Nhược điểm: - Thời gian thi công là hơn trong các trình duyệt IE, 90 + millsec

3 Way: Sử dụng jQuery để tạo DOM (Tư vấn cho tôi là don 't sử dụng nó)

var tableBody = $('<tbody></tbody>'), 
    tableElement2 = document.getElementById("employeeList2"), 
     for(var i=0,len=testData.length; i<len; i++){ 
      tableRow = $("<tr></tr>"); 
      for(var k in testData[i]){ 
       rowCell = $("<td></td>"); 
       rowCell.append(testData[i][k]); 
       tableRow.append(rowCell); 
      } 
      tableBody.append(tableRow); 
     } 
tableElement2.append(tableBody); 

Ưu điểm: - dễ dàng thêm các thuộc tính/lớp/phong cách trên các yếu tố và rất dễ dàng để đọc và đứng vững được chính.

Nhược điểm: - thời gian tồi tệ nhất thực hiện trên tất cả các trình duyệt (220 ms 330 ms), số chậm nhất là trong IE

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