通过JavaScript生成的表格,在Internet Explorer中渲染缓慢

4
我正在开发一个包含大表格的Web应用程序页面,其中有12列并且在某些情况下高达300行。我在Internet Explorer中很难使表格快速渲染出来。我在这个测试代码片段中复制了我的困难:http://jsfiddle.net/dSFz5/。以下是在一台配备4GB RAM的Intel Quad Core Q8200上使用IE9进行的一些基准测试结果:
50行,12列:432ms
100行,12列:1023ms
200行,12列:2701ms
400行,12列:8107ms
800行,12列: 24619ms
呈指数级增长。
我设法找到一些代码,可以使Internet Explorer更快地渲染相同的测试表格。但由于我正在使用mustache.js模板来渲染单元格和行(使所有HTML标记都不在JavaScript中),因此无法使用这些DOM方法:http://jsfiddle.net/bgzLG/。以下是基准测试结果:
50行,12列:37ms
100行,12列:72ms
200行,12列:146ms
400行,12列:324ms
800行,12列:566ms
我不能像第二个示例那样逐个构建表格,因为使用客户端模板时需要注入mustache返回的HTML字符串。如果你开始插入.innerHTML,性能会再次下降。有人能推荐一种以与客户端模板的使用兼容的更有效率的方式构建表格吗?分页是解决这个问题的一种方法,但我想解决问题本身。任何建议都将不胜感激!

我认为你在每次循环迭代时进行的DOM遍历,以及12次的DOM操作是导致性能下降的原因。尽可能少地触碰DOM。先进行所有处理,然后再将其添加到DOM中。 - Stefan H
3个回答

6

首先,我建议将字符串的创建与实际表格的创建分开,因为这会增加渲染时间。接下来,您应该尝试在将整个表格附加到主体之前创建整个表格,以最小化重绘/回流的次数。最后,我建议在IE中使用数组连接,因为该浏览器中的字符串连接会反复分配越来越大的内存块。当您使用数组连接时,浏览器只会分配足够容纳整个字符串的内存。

var strings = [],
    table = ['<table>'],
    i, j;

for (i = 0; i < 1000; i += 1) {
    strings[i] = [];

    for (j = 0; j < 12; j += 1) {
        strings[i][j] = randomString();
    }        
}

var start = new Date().getTime();

for (i = 0; i < 1000; i += 1) {
    table.push('<tr>');

    for (j = 0; j < 12; j += 1) {
        table.push('<td>', strings[i][j], '</td>');
    }

    table.push('</tr>');
}

table.push('</table>');

$('body').append(table.join(''));

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time + 'ms');​

使用这种方法,在IE9中我得到了以下结果:
100 rows is ~9ms
200 rows is ~19ms
500 rows is ~51ms
1000 rows is ~119ms
5000 rows is ~526ms

我相信我们可以进一步优化它,但这应该已经足够处理300行数据(约30毫秒),这也是你所说的目标。此外,它还将保持在任何UI交互下低于约50毫秒的黄金基准。


你需要50点声望才能在不是你自己的帖子上发表评论。如果你继续回答问题,几个小时内就应该可以获得这些声望 :) - Tim Post
似乎我的评论消失了。:(不过感谢您提醒,我已经更新了我的回答,包括一些基准测试和解释。希望原帖主能看到它。 - Steve Savoy
太好了!为了让你的解决方案适用于我的代码,我不得不编写一个函数类来收集和绑定事件到元素(通过元素ID),在它们被添加到DOM后。但最终,它并没有使代码复杂化,并且运行非常快。对于IE6和IE7用户来说,这是唯一的方法,可以在浏览器端构建具有事件处理的大型表格。IE6和IE7无法处理在内存中构建大型DOM元素。 - Elliot B.

2

使用以下内容:

var table = $('<table></table>');

for (var a=0; a<200; a++) {


    var tr = $('<tr></tr>');    
    for (var b=0; b<12; b++) {

        tr.append('<td>'+randomString()+'</td>');        

    }

table.append(tr);
}

$('body').append(table); 

将表格在添加到DOM之前先在内存中构建,可以减少约130毫秒的时间。

以下是我的基准测试结果:

100  - 346
200  - 670
500  - 2037
1000 - 4272
2000 - 10502
原始数据:
100 - 408 200 - 898 500 - 2987 1000 - 10202 2000 - 41305

Jquery是相当酷的东西 :) 越少操作DOM,越好。祝你好运! - Stefan H

0
我认为模板在这里并不适用,因为性能原因。使用DOM操作构建表格,并首先添加所有行,然后再附加它是有意义的。这会产生很大的差异。
你也可以尝试像jqGrid这样的东西:它处理大量的行,而只有可见的行在html屏幕上呈现(虚拟列表)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接