如何加速IE8中innerHTML的读取?

7

我正在使用带有DataTable插件的JQuery,现在在以下代码行中遇到了性能问题。

aLocalData[jInner] = nTds[j].innerHTML; // jquery.dataTables.js:2220

我有一个ajax调用,返回的结果是HTML格式的字符串。我将它们转换为HTML节点,这部分没问题。

var $result = $('<div/>').html(result).find("*:first");
// simlar to $result=$(result) but much more faster in Fx

然后我启用了将普通表格转换为可排序数据表的结果。在Firefox中速度可以接受(大约900行需要4秒),但在IE8中速度不可接受(需要超过100秒)。

我使用内置分析器进行了深入检查,并发现上述单行代码占用了99.9%的时间,我该如何加快速度?有什么我错过的吗?

            nTrs = oSettings.nTable.getElementsByTagName('tbody')[0].childNodes;
            for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
            {
                if ( nTrs[i].nodeName == "TR" )
                {
                    iThisIndex = oSettings.aoData.length;
                    oSettings.aoData.push( {
                        "nTr": nTrs[i],
                        "_iId": oSettings.iNextId++,
                        "_aData": [],
                        "_anHidden": [],
                        "_sRowStripe": ''
                    } );

                    oSettings.aiDisplayMaster.push( iThisIndex );

                    aLocalData = oSettings.aoData[iThisIndex]._aData;
                    nTds = nTrs[i].childNodes;
                    jInner = 0;

                    for ( j=0, jLen=nTds.length ; j<jLen ; j++ )
                    {
                        if ( nTds[j].nodeName == "TD" )
                        {
                            aLocalData[jInner] = nTds[j].innerHTML; // jquery.dataTables.js:2220

                            jInner++;
                        }
                    }
                }
            }

我认为浏览器在处理900行的内容时并不是特别擅长。在Firefox中,快速的JavaScript可以帮助你,但IE在脚本方面要慢得多。 - Bart van Heukelom
1
我建议你使用某种分页机制,我们在IE的另一个网格控件中遇到了相同的问题,javascript引擎的性能很糟糕,所以我们最终让用户有能力分页结果(或者等待IE)。 - bleeeah
只是好奇,将该行代码替换为var result = nTds[j].innerHTML;会对性能产生什么影响?(暂不考虑是否会导致错误) - Nick Craver
我之前尝试过: var temp; (function MARK(nTd){ temp=nTd.innerHTML; })(nTd[i]); aLocalData[jInner]=temp;而IE9内置的分析器显示了标记所消耗的所有时间。 - Dennis C
5个回答

4

1
你有一个很棒的网页。我刚刚把链接分享给了几个朋友。在升级过程中会很有用。 - Egor Pavlikhin
我有几个表格,大小不同,在页面上看起来正常。它们没有滚动条,但在滚动时保持其标题可见。 我正在使用jquery-datatable的FixedHeader插件。是否有类似于yui-datatable的东西可以做到这一点?例如:http://www.datatables.net/release-datatables/extras/FixedHeader/ 当表格在屏幕内时,看起来很正常。 当表格部分在屏幕上时,标题仍然可见。 当表格在屏幕外时,没有额外的标题。 - Dennis C
有一种更接近“HTML”的东西。只需使用ScrollingDataTable:http://developer.yahoo.com/yui/datatable/#scrolling。查看实时演示http://developer.yahoo.com/yui/examples/datatable/dt_fixedscroll.html - Paul Tarjan
Tarjan,我看了一下这个例子,但它并不是我想要的效果。 - Dennis C
你来决定吧。我会选择现在能用的东西,然后稍后再调整用户界面。 - Paul Tarjan

1
我建议避免在IE中使用innerHTML,而是尝试使用XML DOM元素。我尝试过不同的循环修复方法,但延迟来自于提取HTML元素的值。问题在于IE的Javascript引擎,需要解决方案才能获得可接受的性能。
经过多次尝试和错误,我得出了比innerHTML更好的改进方案:
   var start = new Date().getTime()
     var resp=[];
     var dataTbl = $(data).find('#tbl').get(0);  // jquery Ajax call to html, .get(0) for real DOM
     var dataObj = dataTbl.rows;  
     for (var i = 1, l = dataObj.length; i < l; i++) { 
     resp[i] = { 
        label: dataObj[i].firstChild.firstChild.nodeValue,
        value: dataObj[i].lastChild.firstChild.nodeValue
      };
    };
  alert("On Array 5(DOM:For:array[index]:i++:): Milliseconds: " + ( new Date().getTime() - start) );

IE8与FireFox 3性能(非科学)比较:将一个包含2列的表格(1655行)转换为对象数组

  • 数组1(JQuery .each):毫秒数:20203 / 68
  • 数组2(for:array.push):毫秒数:19531 / 41
  • 数组3(while:array.push):毫秒数:19609 / 44
  • 数组4(For:array[index]):毫秒数:20562 / 326
  • 数组5(DOM:For:array[index]:i++:):毫秒数:797 / 245 ***获胜者
  • 数组6(DOM:For:array[index]:i+=):毫秒数:828 / 245
  • 数组7(DOM:For:array.push:i++):毫秒数:797 / 250

1

我已经应用了自己的补丁,但仍在寻找真正的解决方案,在IE中仍然非常缓慢(10+秒),但可以接受。

我读取innerHTML一次行并拆分自己的行。

                    // For whom in interest
                    // Tested on IE8, Fx3.5
                    .....
                    aLocalData = oSettings.aoData[iThisIndex]._aData;
                    jInner = 0;
                    if(nTrs[i].getElementsByTagName('table').length == 0){
                        nTds =$.trim(nTrs[i].innerHTML).split(/<\/td>\s*/i);
                        for(j=0, jLen=nTds.length; j<jLen; j++){
                            aLocalData[jInner]=nTds[j].replace(/<td[\w\W]*?>/i,'');
                            jInner++;
                        }
                        continue;
                    }
                    nTds = nTrs[i].childNodes;
                    .....

如果有人知道为什么innerHTML很慢,请告诉我。


1
一个有10列和900行的表将会调用innerHTML函数9000次。相反,将innerHTML内容附加到数组中,并在表格末尾仅调用一次innerHTML。
类似于:
var contentArray = ["","","Cell Content","",""];
container.innerHTML(contentArray.join(""));
这样,在表格构建过程中只调用一次innerHTML。否则,您可以在每行末尾调用innerHTML,从而减少调用innerHTML的次数至900次。

代码来自jquery-datatable,它已经支持HTML表格和AJAX作为数据源。 - Dennis C

1

你有没有考虑使用 XML 数据岛来实现这个功能?这可能有点棘手,但速度相当快。以下是如何将 HTML 表格绑定到 XML 数据岛的方法:

http://www.devx.com/tips/Tip/14109

在这个岛上,你可以从远程源加载数据,就像使用Ajax一样。


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