是否有使用javascript生成html的最佳实践


103

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

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

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

是否有最佳做法?我可以看到几种方法:

  1. 连接字符串
  2. 创建元素
  3. 使用模板插件
  4. 在服务器上生成html,然后通过JSON进行投放。

1
您还可以检查下划线js:documentcloud.github.com/underscore/#template它与骨干
.js的

1-4中的选择:取决于要注入的内容。(首选4表示更大的内容)总共需要追加多少个不同的html部分(3或4)。某人熟悉的东西。(对开发时间的影响)。如果您不知道任何工具,那只是一个小模态,一旦我不知道艾米会比纯粹的js更好的方法来进行注入(1-2)
partizanos

Answers:


68

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

模板还不是很不成熟,并且您会在大多数主要的Javascript框架中看到它的弹出。

这是JQuery模板插件中的一个示例,它可以节省性能损失,而且非常非常简单:

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

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

我说走很酷的路线(性能更好,更易于维护),并使用模板。


13
JQuery的模板似乎是死了,看到stackoverflow.com/questions/7911732/...
詹姆斯麦克马洪

4
@吉姆·菲奥拉托(Jim Fiorato):链接已死:s
Adrien Be)

2
正如艾德琳(Adrien)指出的那样,链接已经死了。建议您更新答案以包括:Mustache.js
Mr. Polywhirl 2014年

1
有人可以解释一下,为什么基于jQuery的答案被接受吗?我怀疑这是最佳做法!
2016年

1
@WoIIe更糟糕的是,jQuery插件已死,因此此答案已过时。
富兰克林于

13

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

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.4s进行测试,但是IE7在20分钟后还没有完成!(不,我不是在开玩笑。)使用数组IE​​的速度非常快。


我很久以前才切换浏览器,所以我受的不是那么多。IE浏览器是一个可怕的浏览器,但它正在变得越来越好。但是我怀疑我是否会转回去。
一些

1
在第一种方法中看到的性能降低很可能是因为必须将结果字符串重新分配200次,并且内存分配可能很慢。经过两次迭代,您可以进行“ testingtesting”。经过三轮迭代后,该字符串将被丢弃,并为“ testing-testing-testing”分配了足够的空间。以此类推,随着长度的逐渐增加200次。但是s.join()会分配一个新字符串,该字符串足够长,可以容纳所有字符串,然后在每个字符串中进行复制。一次分配,快得多。
EricP

1
@JoeCoder,同意,它是Shlemiel的Painter算法。joelonsoftware.com/articles/fog0000000319.html
Jodrell

8

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

我将在Prototype中给出每个示例。

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

方法1:

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

方法2:

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

使用字符串而不是DOM元素显式生成HTML的性能更高(假设字符串串联不是真正的问题)并且可读性强。
罗德里克·查普曼

在IE中,字符串串联始终是一个问题。请改用数组。
大约

7

也许更现代的方法是使用模板语言(例如Mustache),该语言具有多种语言的实现,包括javascript。例如:

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

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

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

如果你需要更多复杂的模板(if语句,循环等),你可以使用手把它有更多的功能,并与小胡子兼容。



4

您可以将模板HTML添加到隐藏div中的页面中,然后使用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*/})

3

披露:我是BOB的维护者。

有一个JavaScript库,称为BOB,可以使此过程更加轻松。

对于您的特定示例:

<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在Bower上可用,因此您可以通过运行获得它bower install BOB


2

是否有最佳做法?我可以看到几种方法:

  1. 连接字符串
  2. 创建元素
  3. 使用模板插件
  4. 在服务器上生成html,然后通过JSON进行投放。

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

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

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

这种范例近来经常被采用,并且整个框架都是围绕这种方法构建的(例如,参见ribs.js)。

2)出于性能考虑,最好在字符串中构建html,然后将其整体注入到页面中。

3)这是另一种选择,并且采用了Web应用程序框架。其他用户发布了各种可用的模板引擎。我给您的印象是,您具有评估它们并决定是否遵循这条道路的技能。

4)另一种选择。但是将其作为纯文本/ html来提供;为什么使用JSON?我不喜欢这种方法,因为将PHP(您的服务器语言)与HTML混合使用。但是我经常采用它作为选项14之间的合理折衷。


我的回答:您已经在寻找正确的方向。

我建议像我一样采用介于14之间的方法。否则,采用Web框架或模板引擎。

只是根据我的经验我的意见...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.