有没有用 javascript 生成 html 的最佳实践

我正在调用一个以 JSON 格式返回对象数组的 Web 服务。我想用这些对象并用 HTML 填充一个 div。假设每个对象都包含一个 url 和一个名称。

如果我想为每个对象生成以下 HTML:

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

有什么最好的做法吗? 我可以看到几种做法:

  1. 串联字符串
  2. Create elements
  3. 使用模板插件
  4. 在服务器上生成 html,然后通过 JSON 提供服务。
98905 次浏览

前两种选择中的任何一种都是常见且可接受的。

我将在 原型机中给出每个例子。

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

方法一:

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

Approach #2:

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

选项 # 1和 # 2将是您最直接的选项,但是,对于这两个选项,您将感受到构建字符串或创建 DOM 对象对性能和维护的影响。

模板化并不是那么不成熟,而且你可以看到它在大多数主要的 Javascript 框架中出现。

下面是 JQuery 模板插件中的一个例子,它将为您节省性能损失,而且非常、非常简单:

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


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

我认为应该采取更酷的方式(更好地执行,更易于维护) ,并使用模板。

Here's an example, using my 翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳翻译: 奇芳 plug-in for jQuery:

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

您可以在一个隐藏的 div 中将模板 HTML 添加到页面,然后使用 cloneNode 和您喜欢的库的查询工具来填充它

/* 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*/})

如果必须连接字符串而不是普通的:

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

使用临时数组:

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

使用数组要快得多,尤其是在 IE 中。前段时间我用 IE7,Opera 和 FF 做了一些字符串测试。Opera 只用了0.4秒就完成了测试,但是 IE7在20分钟后还没有完成!(不,我不是在开玩笑。)使用数组 IE 是非常快的。

也许更现代的方法是使用模板语言,比如 胡子,它有许多语言的实现,包括 javascript。例如:

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


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

您甚至还获得了额外的好处——您可以在其他地方重用相同的模板,例如服务器端。

如果需要更复杂的模板(If 语句、循环等) ,可以使用具有更多功能并与 Mustache 兼容的 车把

有什么最好的做法吗? 我可以看到几种做法:

  1. 串联字符串
  2. Create elements
  3. 使用模板插件
  4. 在服务器上生成 html,然后通过 JSON 提供服务。

1) 这是一个选项。在客户端使用 JavaScript 构建 html,然后将其作为一个整体注入到 DOM 中。

请注意,这种方法背后有一个范例: 服务器只输出数据,(在交互的情况下)通过 AJAX 请求异步地从客户端接收数据。客户端代码作为独立的 JavaScript Web 应用程序运行。

Web 应用程序可以运行,渲染界面,即使没有服务器启动(当然它不会显示任何数据或提供任何类型的交互)。

这种模式最近经常被采用,整个框架都是围绕这种方法构建的(参见 backbone.js)。

2) 出于性能原因,如果可能的话,最好在字符串中构建 html,然后将其作为一个整体注入到页面中。

3) 这是另一个选项,同时采用了 Web 应用程序框架。其他用户已经发布了各种可用的模板引擎。我的印象是,你有能力评估他们,并决定是否遵循这条道路。

4) Another option. But serve it up as a plain text/html; why JSON? I don't like this approach because mixes PHP (your server language) with Html. But I adopt it often as a reasonable compromise between option 1 and 4.


我的回答是: 你已经在朝正确的方向看了。

I suggest to adopt an approach between 1 and 4 like I do. Otherwise adopt a web framework or templating engine.

根据我的经验。

披露: 我是 BOB 的维护者。

有一个名为 BOB的 javascript 库使得这个过程更加简单。

举个具体的例子:

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

这可以通过以下代码与 BOB 一起生成。

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

或者使用更短的语法

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

这个库非常强大,可以用来创建具有数据插入的非常复杂的结构(类似于 d3) ,例如:

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 目前不支持将数据注入到 DOM 中。这是托德医生的诊断结果。现在,您可以简单地将输出与普通 JS 或 jQuery 一起使用,并将其放在任何需要的位置。

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());

我创建这个库是因为我不喜欢 jquery 和 d3这样的替代品。代码非常复杂,难以阅读。在我看来,和 BOB 一起工作显然是有偏见的,更加愉快。

BOB is available on 鲍尔, so you can get it by running bower install BOB.