在javascript性能中动态创建大型html表

我有一个用于数据分析的应用程序,我在创建表时遇到了一些性能问题。 数据是从文档中提取的,重要的是所有数据都显示在一个页面上(不幸的是,分页不是一个选项)。

使用jQuery,我向服务器发出ajax请求以检索数据。 完成请求后,我将数据传递给输出函数。 输出函数使用for循环遍历数据数组并将行连接到变量。 循环完成后,包含该表的变量将附加到页面上的现有div,然后我继续将事件绑定到表以处理数据。

使用一小组数据(~1000-2000行),它的工作效果相对较好,但有些数据集包含超过10,000行,导致Firefox崩溃,关闭或无响应。

我的问题是,有没有更好的方法来完成我正在做的事情?

这是一些代码:

//This function gets called by the interface with an id to retrieve a document function loadDocument(id){ $.ajax({ method: "get", url: "ajax.php", data: {action:'loadDocument',id: id}, dataType: 'json', cache: true, beforeSend: function(){ if($("#loading").dialog('isOpen') != true){ //Display the loading dialog $("#loading").dialog({ modal: true }); }//end if },//end beforesend success: function(result){ if(result.Error == undefined){ outputDocument(result, id); }else{  }//end if if($('#loading').dialog('isOpen') == true){ //Close the loading dialog $("#loading").dialog('close'); }//end if }//end success });//end ajax };//end loadDocument(); //Output document to screen function outputDocument(data, doc_id){ //Begin document output var rows = ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; for(var i in data){ var recordId = data[i].id; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += ''; }//end for rows += ''; rows += '
IDStatusNameActionsOrigin
' + recordId + '' + data[i].status + '' + data[i].name + ''; rows += ''; rows += ''; rows += '' + data[i].origin + '
'; $('#documentRows').html(rows);

我最初使用jQuery每个循环,但切换到for循环,削减了一些ms。

我想过使用谷歌齿轮这样的东西来尝试卸载一些处理(如果在这种情况下可能的话)。

有什么想法吗?

joinHi,

渲染是一个问题,但是在循环中连接这么多字符串也存在问题,特别是一旦字符串变得非常大。 最好将字符串放入数组的各个元素中,然后最终使用“join”一次创建巨大的字符串。 例如

 var r = new Array(); var j = -1, recordId; r[++j] = ''; for (var i in data){ var d = data[i]; recordId = d.id; r[++j] = ''; } r[++j] = '
IDStatusNameActionsOrigin
'; r[++j] = recordId; r[++j] = ''; r[++j] = d.status; r[++j] = ''; r[++j] = d.name; r[++j] = ''; r[++j] = d.origin; r[++j] = '
'; $('#documentRows').html(r.join(''));

此外,我将使用此处显示的数组索引方法,而不是使用“推送”,因为除了谷歌浏览器之外,所有浏览器都更快,根据这篇文章 。

显示那么多行导致浏览器的渲染引擎变慢,而不是JavaScript引擎。 不幸的是,你不能做很多事情。

最好的解决方案是不要通过分页或虚拟滚动同时显示这么多行。

构建字符串的方式将导致大量垃圾回收。

随着字符串变得越来越长,javascript引擎必须继续分配更大的缓冲区并丢弃旧的缓冲区。 最终,如果不回收所有旧字符串的剩余部分,它将无法分配足够的内存。

随着字符串变长,这个问题变得更糟。

而是尝试使用jQuery操作API一次向DOM添加新元素

还要考虑仅渲染可见内容并实现自己的滚动。

你可以做几件事来提高性能:

  1. 你的rows变量越来越大,所以不要将html存储在一个变量中。 解决方案可以是$.each()函数以及将元素附加到DOM中的每个函数。 但这是一个小调整。
  2. Html生成很好,但您可以尝试DOM创建和追加。 像$('

    ')

  3. 最后,这肯定会解决您的问题:在第一个ajax调用中使用多个ajax调用收集可用的数据量并获取大约1,000个或者可能是更多数据。 并使用其他调用来收集剩余数据。 如果需要,可以明智地使用同步调用或异步调用。

但尽量避免存储价值。 你的DOM大小将是巨大的,但它应该适用于现代浏览器而忘记IE6。

@ fuel37:例子

 function outputDocumentNew(data, doc_id) { //Variable DOM's var rowSample = $('').addClass('row-class'); var colSample = $('').addClass('col-class'); var spanSample = $('').addClass('span-class'); var inputButtonSample = $('').addClass('input-class'); //DOM Container var container = $('#documentRows'); container.empty().append('
'); //Static part var head = '\ \ ID\ Status\ Name\ Actions\ Origin\ \ '; container.append(head); var body = $(''); container.append(body); //Dynamic part $.each(data, function (index, value) { var _this = this; //DOM Manupulation var row = rowSample.clone(); //Actions var inpFailOne = inputButtonSample.clone().val('F').attr('rev', _this.id).addClass('failOne').click(function (e) { //do something when click the button. }); var inpPromoteOne = inputButtonSample.clone().val('P').attr('rev', _this.id).addClass('promoteOne').click(function (e) { //do something when click the button. }); row .append(colSample.clone().append(_this.id)) .append(colSample.clone().append(spanSample.colne().addClass('status').append(_this.status))) .append(colSample.clone().append(spanSample.colne().addClass('name').append(_this.name))) .append(colSample.clone().append(inpFailOne).append(inpPromoteOne)) .append(colSample.clone().append(_this.origin)); body.append(row); }); }

在这个过程中,您需要创建和维护用于操作的id或类。 您可以控制绑定事件并操纵那里的每个元素。

回答格式化

如果你这样做会发生什么

 for(var i in data){ var record = data[i]; var recordId = record.id; rows += ''; rows += '' + recordId + ''; rows += '' + data[i].status + ''; rows += '' + record.name + ''; rows += ''; rows += ''; rows += ''; rows += ''; rows += '' + record.origin + ''; rows += ''; }//end for 

对于其他人的建议(我还没有足够的声誉来评论,抱歉!),您可以尝试使用TableSorter插件来处理一次只显示可用数量的数据。

我不知道它在很多行中的表现如何,但它们的示例数据大约是1000行。

这对JS性能没有帮助,但会减轻浏览器渲染器的负担。

可以尝试这个……

改善循环

改进String Concat

 var tmpLst = []; for (var i=0, il=data.length; i'); tmpLst.push(''); ...ect... } rows += tmpLst.join(''); 

这可能会挤压额外的性能……

 var lstReset = i * lstReset.length; tmpLst[lstReset + 1]='