Có phương pháp hay nhất để tạo html bằng javascript không


103

Tôi đang gọi một dịch vụ web trả về một mảng các đối tượng trong JSON. Tôi muốn lấy các đối tượng đó và điền một div bằng HTML. Giả sử mỗi đối tượng chứa một url và một tên.

Nếu tôi muốn tạo HTML sau cho từng đối tượng:

<div><img src="the url" />the name</div>

Có phương pháp nào tốt nhất cho việc này không? Tôi có thể thấy một số cách để làm điều đó:

  1. Nối các chuỗi
  2. Tạo các phần tử
  3. Sử dụng một plugin tạo khuôn mẫu
  4. Tạo html trên máy chủ, sau đó phân phát qua JSON.

1
Bạn cũng có thể kiểm tra dấu gạch dưới js: documentcloud.github.com/underscore/#template Nó chơi rất tốt với backbone.js
luacassus

Lựa chọn mong 1-4: phụ thuộc vào lượng nội dung sẽ được đưa vào. (Ưu tiên 4 cho lớn hơn) tổng cộng bao nhiêu phần html khác nhau sẽ cần được thêm vào (3 hoặc 4). sb quen thuộc với cái gì. (Ảnh hưởng trong thời gian phát triển). Nếu bạn không biết bất kỳ công cụ chỉ là một phương thức nhỏ bé của mình sẽ được tiêm một lần Tôi không biết amy cách tốt hơn so với js tinh khiết để làm điều đó (1-2)
partizanos

Câu trả lời:


68

Tùy chọn # 1 và # 2 sẽ là các tùy chọn chuyển tiếp tức thì nhất của bạn, tuy nhiên, đối với cả hai tùy chọn, bạn sẽ cảm nhận được tác động về hiệu suất và bảo trì bằng cách xây dựng chuỗi hoặc tạo các đối tượng DOM.

Templating không phải là tất cả những gì chưa trưởng thành và bạn đang thấy nó bật lên trong hầu hết các framework Javascript chính.

Đây là một ví dụ trong Plugin mẫu JQuery sẽ giúp bạn tiết kiệm hiệu suất và thực sự rất đơn giản:

var t = $.template('<div><img src="${url}" />${name}</div>');

$(selector).append( t , {
     url: jsonObj.url,
     name: jsonObj.name
});

Tôi nói rằng hãy đi theo con đường tuyệt vời (và hoạt động tốt hơn, dễ bảo trì hơn) và sử dụng khuôn mẫu.


13
JQuery templating dường như đã chết, hãy xem stackoverflow.com/questions/7911732/…
James McMahon

4
@Jim Fiorato: liên kết đã chết: s
Adrien Be

2
Liên kết đã chết, như Adrien chỉ ra. Đề nghị bạn cập nhật câu trả lời của mình để bao gồm: Mustache.js
Ông Polywhirl

1
Ai đó có thể vui lòng giải thích, tại sao câu trả lời dựa trên jQuery lại được chấp nhận không? Tôi nghi ngờ rằng đây là phương pháp hay nhất!
WoIIe

1
@WoIIe Tệ hơn nữa, plugin jQuery đã chết, vì vậy câu trả lời này đã lỗi thời.
Franklin Yu

13

Nếu bạn hoàn toàn phải nối các chuỗi, thay vì nối bình thường:

var s="";
for (var i=0; i < 200; ++i) {s += "testing"; }

sử dụng một mảng tạm thời:

var s=[];
for (var i=0; i < 200; ++i) { s.push("testing"); }
s = s.join("");

Sử dụng mảng nhanh hơn nhiều, đặc biệt là trong IE. Tôi đã thực hiện một số thử nghiệm với chuỗi một thời gian trước với IE7, Opera và FF. Opera chỉ mất 0,4 giây để thực hiện bài kiểm tra, nhưng IE7 vẫn chưa hoàn thành sau 20 PHÚT !!!! (Không, tôi không đùa đâu.) Với mảng IE đã rất nhanh.


Tôi đã chuyển đổi trình duyệt một thời gian dài, vì vậy tôi không bị như vậy nhiều. IE là một trình duyệt tồi tệ nhưng nó đang trở nên tốt hơn. Nhưng tôi nghi ngờ rằng tôi sẽ không bao giờ quay trở lại.
một số

1
Hiệu suất chậm được thấy trong phương pháp đầu tiên có thể là do chuỗi kết quả phải được phân bổ lại 200 lần và cấp phát bộ nhớ có thể chậm. Sau hai lần lặp lại, bạn có "testingtesting". Sau ba lần lặp, chuỗi đó sẽ bị loại bỏ và bộ nhớ có đủ chỗ cho "testtestingtesting" được cấp phát. Và cứ như vậy 200 lần với độ dài tăng dần. Tuy nhiên s.join () phân bổ một chuỗi mới do kết quả đủ dài để phù hợp với tất cả chúng, sau đó sao chép từng chuỗi. Một phân bổ, nhanh hơn nhiều.
EricP

1
@JoeCoder, đã đồng ý, đó là thuật toán Shlemiel The Painter. joelonsoftware.com/articles/fog0000000319.html
Jodrell

8

Cả hai lựa chọn đầu tiên đều phổ biến và được chấp nhận.

Tôi sẽ đưa ra các ví dụ về từng cái trong Prototype .

// assuming JSON looks like this:
// { 'src': 'foo/bar.jpg', 'name': 'Lorem ipsum' }

Cách tiếp cận # 1:

var html = "<div><img src='#{src}' /> #{name}</div>".interpolate(json);
$('container').insert(html); // inserts at bottom

Cách tiếp cận # 2:

var div = new Element('div');
div.insert( new Element('img', { src: json.src }) );
div.insert(" " + json.name);
$('container').insert(div); // inserts at bottom

Việc tạo HTML một cách rõ ràng bằng các chuỗi thay vì các phần tử DOM thì hiệu quả hơn (giả sử việc nối chuỗi không phải là vấn đề thực sự) và có thể đọc được.
Rodrick Chapman 21/10/08

Trong IE, nối chuỗi luôn là một vấn đề. Sử dụng một mảng để thay thế.
một số

7

Có lẽ một cách tiếp cận hiện đại hơn là sử dụng một ngôn ngữ tạo khuôn mẫu như Mustache , ngôn ngữ này có nhiều ngôn ngữ được triển khai, bao gồm cả javascript. Ví dụ:

var view = {
  url: "/hello",
  name: function () {
    return 'Jo' + 'hn';
  }
};

var output = Mustache.render('<div><img src="{{url}}" />{{name}}</div>', view);

Bạn thậm chí còn nhận được một lợi ích bổ sung - bạn có thể sử dụng lại các mẫu tương tự ở những nơi khác, chẳng hạn như phía máy chủ.

Nếu bạn cần các mẫu phức tạp hơn (câu lệnh if, vòng lặp, v.v.), bạn có thể sử dụng Handlebars có nhiều tính năng hơn và tương thích với Mustache.


6

Đây là một ví dụ, sử dụng trình cắm thêm Mẫu đơn giản của tôi cho jQuery:

var tmpl = '<div class="#{classname}">#{content}</div>';
var vals = {
    classname : 'my-class',
    content   : 'This is my content.'
};
var html = $.tmpl(tmpl, vals);

1
Khéo léo. Tôi có thể đã sử dụng một cái gì đó giống như trong một dự án lớn cách đây vài tháng.
Rodrick Chapman 21/10/08

Đúng. Cô đọng và gọn gàng!
ajitweb

4

Bạn có thể thêm HTML mẫu vào trang của mình trong một div ẩn và sau đó sử dụng cloneNode và các phương tiện truy vấn của thư viện yêu thích của bạn để điền nó

/* CSS */
.template {display:none;}

<!--HTML-->
<div class="template">
  <div class="container">
    <h1></h1>
    <img src="" alt="" />
  </div>
</div>

/*Javascript (using Prototype)*/
var copy = $$(".template .container")[0].cloneNode(true);
myElement.appendChild(copy);
$(copy).select("h1").each(function(e) {/*do stuff to h1*/})
$(copy).select("img").each(function(e) {/*do stuff to img*/})

3

Tiết lộ: Tôi là người duy trì BOB.

Có một thư viện javascript giúp quá trình này dễ dàng hơn rất nhiều được gọi là BOB .

Đối với ví dụ cụ thể của bạn:

<div><img src="the url" />the name</div>

Điều này có thể được tạo với BOB bằng đoạn mã sau.

new BOB("div").insert("img",{"src":"the url"}).up().content("the name").toString()
//=> "<div><img src="the url" />the name</div>"

Hoặc với cú pháp ngắn hơn

new BOB("div").i("img",{"src":"the url"}).up().co("the name").s()
//=> "<div><img src="the url" />the name</div>"

Thư viện này khá mạnh và có thể được sử dụng để tạo các cấu trúc rất phức tạp có chèn dữ liệu (tương tự như d3), ví dụ:

data = [1,2,3,4,5,6,7]
new BOB("div").i("ul#count").do(data).i("li.number").co(BOB.d).up().up().a("a",{"href": "www.google.com"}).s()
//=> "<div><ul id="count"><li class="number">1</li><li class="number">2</li><li class="number">3</li><li class="number">4</li><li class="number">5</li><li class="number">6</li><li class="number">7</li></ul></div><a href="www.google.com"></a>"

BOB hiện không hỗ trợ đưa dữ liệu vào DOM. Đây là trên máy chơi chữ. Hiện tại, bạn có thể chỉ cần sử dụng đầu ra cùng với JS thông thường hoặc jQuery và đặt nó ở bất cứ đâu bạn muốn.

document.getElementById("parent").innerHTML = new BOB("div").insert("img",{"src":"the url"}).up().content("the name").s();
//Or jquery:
$("#parent").append(new BOB("div").insert("img",{"src":"the url"}).up().content("the name").s());

Tôi tạo thư viện này vì tôi không hài lòng với bất kỳ lựa chọn thay thế nào như jquery và d3. Mã rất phức tạp và khó đọc. Làm việc với BOB theo ý kiến ​​của tôi, điều này rõ ràng là thiên vị, dễ chịu hơn rất nhiều.

BOB có sẵn trên Bower , vì vậy bạn có thể lấy nó bằng cách chạy bower install BOB.


2

Có phương pháp nào tốt nhất cho việc này không? Tôi có thể thấy một số cách để làm điều đó:

  1. Nối các chuỗi
  2. Tạo các phần tử
  3. Sử dụng một plugin tạo khuôn mẫu
  4. Tạo html trên máy chủ, sau đó phân phát qua JSON.

1) Đây là một tùy chọn. Xây dựng html bằng JavaScript ở phía máy khách và sau đó đưa nó vào DOM nói chung.

Lưu ý rằng có một mô hình đằng sau cách tiếp cận này: máy chủ chỉ xuất dữ liệu và (trong trường hợp tương tác) nhận dữ liệu từ máy khách không theo thời gian với các yêu cầu AJAX. Mã phía máy khách được chọn làm ứng dụng web JavaScript độc lập.

Ứng dụng web có thể hoạt động, hiển thị giao diện, ngay cả khi máy chủ không hoạt động (tất nhiên nó sẽ không hiển thị bất kỳ dữ liệu nào hoặc cung cấp bất kỳ loại tương tác nào).

Mô hình này đang được áp dụng thường xuyên trong thời gian gần đây và toàn bộ khung công tác được xây dựng dựa trên cách tiếp cận này (ví dụ: xem backbone.js).

2) Vì lý do hiệu suất, khi có thể, tốt hơn nên xây dựng html trong một chuỗi và sau đó đưa nó vào toàn bộ trang.

3) Đây là một tùy chọn khác, cũng như áp dụng khung Ứng dụng Web. Những người dùng khác đã đăng các công cụ tạo khuôn mẫu khác nhau có sẵn. Tôi có ấn tượng rằng bạn có đủ kỹ năng để đánh giá chúng và quyết định có đi theo con đường này hay không.

4) Một lựa chọn khác. Nhưng phân phát nó dưới dạng văn bản thuần túy / html; tại sao JSON? Tôi không thích cách tiếp cận này vì trộn PHP (ngôn ngữ máy chủ của bạn) với Html. Nhưng tôi thường áp dụng nó như một sự thỏa hiệp hợp lý giữa lựa chọn 14 .


Câu trả lời của tôi: bạn đã và đang nhìn đúng hướng.

Tôi đề nghị áp dụng cách tiếp cận giữa 1 đến 4 như tôi làm. Nếu không, hãy áp dụng khuôn khổ web hoặc công cụ tạo khuôn mẫu.

Chỉ là ý kiến ​​của tôi dựa trên kinh nghiệm của tôi ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.