使用jQuery动态构建HTML表

下面是我用来动态构建HTML表的代码(使用从服务器接收的JSON数据)。

我在加载数据时显示动画的等待(.gif)图形。 但是,当JavaScript函数构建表时,图形会冻结。 起初,我很高兴能够实现这一点(显示表格),我想现在我需要努力提高效率。 至少我需要阻止动画图形冻结。 我可以去静态“加载”显示,但我宁愿让这个方法工作。

我的建议等待显示? 和效率? 可能是建立桌子的更好方法? 或许不是一张桌子,而是一些其他“桌子”就像展示一样

var t = eval( "(" + request + ")" ) ; var myTable = '' ; myTable += '' ; myTable += "" ; myTable += ""; for (var i = 0; i < t.hdrs.length; i++) { myTable += ""; } myTable += "" ; myTable += "" ; myTable += "" ; for (var i = 0; i < t.data.length; i++) { myTable += ''; for (var j = 0; j < t.hdrs.length; j++) { myTable += '"; } myTable += ""; } myTable += "" ; myTable += "
" + header + "
'; if (t.data[i][t.hdrs[j]] == "") { myTable += " " ; } else { myTable += t.data[i][t.hdrs[j]] ; } myTable += "
" ; $("#result").append(myTable) ; $("#PleaseWaitGraphic").addClass("hide"); $(".rslt").removeClass("hide") ;

你基本上想要设置你的循环,所以它们经常会屈服于其他线程。 以下是本文中有关运行CPU密集型操作而不冻结UI的主题的示例代码:

 function doSomething (progressFn [, additional arguments]) { // Initialize a few things here... (function () { // Do a little bit of work here... if (continuation condition) { // Inform the application of the progress progressFn(value, total); // Process next chunk setTimeout(arguments.callee, 0); } })(); } 

至于简化脚本中HTML的生成,如果你正在使用jQuery,你可以试试我的Simple Templates插件。 它通过大幅减少你必须做的连接数来整理整个过程。 在我最近进行了一些重构之后,它也表现得相当不错,这导致了相当大的速度提升 。 这是一个例子(没有为你完成所有的工作!):

 var t = eval('(' + request + ')') ; var templates = { tr : '#{row}', th : '#{header}', td : '#{cell}' }; var table = ''; $.each(t.hdrs, function (key, val) { table += $.tmpl(templates.th, {header: val}); }); ...

我一直在使用JTemplates来完成你所描述的内容。 Dave Ward在他的博客上有一个例子。 JTemplates的主要好处是你的html没有编入你的javascript。 你编写一个模板并调用两个函数让jTemplate从你的模板和你的json构建html。

你正在做的是构建一个字符串,然后在插入时立即解析它。 如何创建一个实际的表元素(即$("

")

),然后依次添加每一行? 当你实际将它插入到页面中时,DOM节点都将被构造,所以它不应该是一个大的命中。

使用innerHTML肯定比使用jQuery的HTML-to-DOM-ifier快得多,后者使用innerHTML但对输入进行了大量处理。

我建议检查chain.js ,以便从JavaScript对象快速构建表和其他重复数据结构。 它是jQuery的一个非常轻量级的智能数据绑定插件。

首先,请查看flydom及其变体,它们将非常有用。 你能提供更多背景吗? 如果这不在onload中并且只是粘贴在页面中,只需将整个内容包装在$(function(){/ * code * /})中就可以清除你遇到问题的所有内容。 内联JS立即执行,这意味着该表的循环。 onload是一个事件,基本上是’超级’。

我的经验是有两个不连续的延迟。 一个是将所有这些字符串连接在一起。 另一种是当浏览器实际尝试渲染字符串时。 通常情况下,它的IE冻结最麻烦,部分原因是它在运行javascript时要慢得多。 这应该会在IE8中变得更好。

在你的案例中,我建议将操作分解为步骤。 比如100行表,首先生成一个有效的10行表。 然后将其输出到屏幕并使用setTimeout将控制权返回给浏览器,以便UI停止阻止。 当setTimeout返回时,你会执行接下来的10行等。

正如其他人所说,使用DOM创建表肯定是“更清洁”。 但是,在性能方面要付出惨重的代价。 请参阅关于此主题的优秀quirksmode文章,该文章有一些您可以自己运行的基准测试。

简而言之,即使在现代JS引擎上,innerHTML也比DOM快得多。

在网上搜索JavaScript和StringBuilder。 拥有JavaScript字符串构建器后,请确保对每个连接使用.append方法。 也就是说,你不希望有任何+连接。 之后,搜索JavaScript并替换HTML。 使用此函数而不是innerHTML

您可以逐位将表插入DOM。 老实说,我不完全确定这是否会对您的问题有所帮助,但值得一试。 我会大致这样做(未经测试的代码,可以进一步细化):

 $("#result").append('
'); $('#myTable').append(''); $('#myTable').append(''); for (var i = 0; i < t.hdrs.length; i++) { $('#myTable thead tr').append(''+header+''); } for (var i = 0; i < t.data.length; i++) { myTr = ''; for (var j = 0; j < t.hdrs.length; j++) { myTr += ''; if (t.data[i][t.hdrs[j]] == "") { myTr += " " ; } else { myTr += t.data[i][t.hdrs[j]] ; } myTr += ""; } myTr += ""; $('#myTable tbody').append(myTr); } $("#PleaseWaitGraphic").addClass("hide"); $(".rslt").removeClass("hide") ;