【问题标题】:Internet Explorer slow to render tables generated via JavaScriptInternet Explorer 渲染通过 JavaScript 生成的表很慢
【发布时间】:2012-02-22 16:04:50
【问题描述】:

我正在处理带有大表的 Web 应用程序的页面。在某些情况下,12 列和多达 300 行。我很难让表格在 Internet Explorer 中快速呈现。我在这段测试代码中复制了我的困难:

http://jsfiddle.net/dSFz5/

在配备 4GB RAM 的英特尔四核 Q8200 上使用 IE9 进行的一些基准测试:
50 行,12 列:432 毫秒
100 行,12 列:1023 毫秒
200 行,12 列:2701 毫秒
400 行,12 列:8107 毫秒
800 行,12 列:24619ms

指数级的糟糕。

我设法找到了一些代码,它们可以在 Internet Explorer 上更快地呈现相同的测试表,但是因为我使用 mustache.js 模板来呈现我的单元格和行(将所有 HTML 标记排除在我的 JavaScript 之外),我'无法使用这些 DOM 方法:

http://jsfiddle.net/bgzLG/

基准测试结果:
50 行,12 列:37 毫秒
100 行,12 列:72 毫秒
200 行,12 列:146 毫秒
400 行,12 列:324 毫秒
800 行,12 列:566 毫秒

我不能像第二个例子那样逐块构造表格,因为使用客户端模板我需要注入 mustache 返回的 HTML 字符串。如果您开始在其中粘贴 .innerHTML,性能会再次下降。

谁能推荐一种以更有效的方式构建表格的方法,以符合客户端模板的使用?

分页是解决此问题的一种方法,但我想自己解决问题。

非常感谢任何建议!

【问题讨论】:

  • 我认为这是您在该循环的每次迭代中执行的 DOM 遍历,然后 DOM 操作 12 次正在杀死它。尽可能少地触摸 DOM。做任何你能做的处理,然后把它添加到 DOM 中。

标签: javascript jquery html internet-explorer browser


【解决方案1】:

首先,我建议将字符串的创建与表的实际创建分开,因为它会在渲染时间方面产生开销。接下来,您应该尝试在将其附加到正文之前创建整个表,以最大限度地减少重绘/重排的数量。最后,我建议在 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 声望才能评论您不拥有的帖子。如果您继续回答问题,您应该可以在几个小时内得到它:)
  • 我的评论好像消失了。 :( 感谢您的提醒。我已经更新了我的答案以包括基准和一些解释。希望 OP 会看到它。
  • 这太棒了!为了使您的解决方案适用于我的代码,我必须编写一个函数类,用于在元素添加到 DOM 后收集事件并将其绑定到元素(通过元素 ID)。但最终,它不会使代码复杂化并且运行速度非常快。对于 IE6 和 IE7 用户,这是您可以在浏览器端构建具有事件处理的大型表的唯一方法。 IE6 和 IE7 无法处理在内存中构建大型 DOM 元素。
【解决方案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); 

缩短了大约 130 毫秒。这是在将表添加到 DOM 之前在内存中构建表。

这是我的基准测试:

100 - 346 200 - 670 500 - 2037 1000 - 4272 2000 - 10502 和你的原件: 100 - 408 200 - 898 500 - 2987 1000 - 10202 2000 - 41305

【讨论】:

  • Jquery 是很酷的东西 :) 接触 DOM 越少越好。祝你好运!
【解决方案3】:

我会说由于性能原因,模板不适合这里。首先使用所有行的 DOM 操作来构建表,然后才附加它是有意义的。这有很大的不同。

您也可以尝试类似 jqGrid 的方法:它处理大量行,而仅在屏幕上以 html(虚拟列表)呈现可见行。

【讨论】:

    猜你喜欢
    • 2011-10-29
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2014-07-25
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多