向页面添加大量元素时性能不佳

时间:2019-03-04 15:11:43

标签: javascript jquery html arrays

我已经生成了一个表格,但是我使用的是<div>而不是<tr><td>。这是一个示例:

<div class="tbl tbl1">
    <div class="thead">
        <div class="tr">
            <div class="td colTitle" style="width: 120px"><span>Title</span></div>
            <div class="td colLink" style="width: 190px"><span>Link</span></div>
            <div class="td colSize numeric" style="width: 75px"><span>Size(MB)</span></div>
            <div class="td colUploadDate" style="width: 75px"><span>UploadDate</span></div>
            <div class="td colOpen" style="width: 50px; max-width: 50px;"><span>Show</span></div>
        </div>
        <div class="tr">
            <div class="td colTitle">
                <input type="text" class="Filter" />
            </div>
            <div class="td colLink">
                <input type="text" class="Filter" />
            </div>
            <div class="td colSize">
                <input type="text" class="Filter" />
            </div>
            <div class="td colUploadDate">
                <input type="text" class="Filter" />
            </div>
            <div class="td colOpen">
            </div>
        </div>
    </div>
    <div class="tbody">
    </div>
</div>

我将使用ajax函数填充tbody。从数据库中获取所有数据后,我将其存储到客户端的数组中。我使用以下代码使用数组arr填充表格。但是,当我有很多行时,要花很多时间在表中显示行。

var res = "";
arr.forEach(function (row) {
    res += "<div class='tr' idattachment='" + row["IdAttachment"] + "' >" +
            "<div class='td colTitle'>" + row["Title"] + "</div>" +
            "<div class='td colLink'>" + row["Name"] + "</div>" +
            "<div class='td colSize'>" + (row["Size"] / (1024 * 1024)).toFixed(2) + "</div>" +
            "<div class='td colUploadDate'>" + row["UploadDate"] + "</div>" +
            "<div class='td colOpen'><a class='link' href='uploads/" + row["Name"] + "'>Open</a></div>" +
            "</div>";
});
$(".tbody").html(res);

有没有更有效的方式将数据加载到表中?

3 个答案:

答案 0 :(得分:1)

我将进行性能分析。我将逐步进行操作,因此,如果您喜欢该模式,可以尝试执行相同的操作。请记住,有时这种分析将表明您无能为力。

绩效目标

无论何时您要存档关卡性能,第一个问题应该是我们要做什么。

正常比例如下。

  • <16ms的动画
  • <100ms立即反应
  • 100-300ms轻微的可察觉的延迟
  • 300-1000ms正在完成任务。
  • > 1s失去专注力。
  • > 10s挫败与放弃任务

看来您正在执行任务,所以目标<= 1s。

关注这些目标时,请遵循数据。

JS

您正在使用forEach似乎是最佳选择。 these answers

String Plus与模板文字无关紧要。 https://jsperf.com/for-vs-foreach/75

点表示法与方括号表示法似乎无关紧要。 https://jsperf.com/template-literal-vs-string-plus/7

JS结论

数据尽可能地优化了您的Javascript。

CSS

未提供CSS。

CSS结论

不确定

渲染

jQuery append vs html vs innerHTML

https://jsperf.com/dot-notation-vs-square-bracket-notation/5

使用innerHTML似乎是一个更好的选择。

渲染结论

将.html更改为innerHTML

知觉

当我在没有CSS的情况下呈现此代码时,您没有提供它。当我渲染10,000个项目时,我的渲染时间开始达到1s。

您可以对渲染进行分页,但是如果执行此操作,则需要加载耗时少于16ms的块。即使您认为没有动画滚动也是一种动画。

当您在低端设备上进行测试并获得1秒内可以渲染多少个项目时,请执行以下操作。我在设备上打1时使用的是10k。 10,000 / 1000 * 15这将为您提供可以在1秒钟内加载而不会中断动画的项目数量。

添加一个微调器或表明工作已完成的内容。因此,用户认为某些事情正在起作用,这可以将时间从<100ms缩短到300-1000ms。

感知结论

分页

添加微调器或正在完成工作。

这就是我所拥有的。祝你好运。

答案 1 :(得分:0)

使用虚拟渲染仅渲染视图中实际存在的行。

Clusterize.js的示例:

var rows = [];
for (var i = 0; i < 10000; i++) {
  rows.push('<tr><td>Row ' + i + '</td></tr>');
}

var clusterize = new Clusterize({
  rows: rows,
  scrollId: 'scrollArea',
  contentId: 'tbody'
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.18.0/clusterize.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/clusterize.js/0.18.0/clusterize.min.css" rel="stylesheet"/>

<div class="clusterize-scroll" id="scrollArea">
  <table>
      <thead class="thead">
          <tr class="tr">
              <td>
                <span>Title</span>
              </td>
          </tr>
      </thead>
      <tbody id="tbody" class="clusterize-content">
        <tr class="clusterize-no-data">
          <td>Loading data…</td>
        </tr>
      </tbody>   
  </table>
</div>

答案 2 :(得分:-1)

在加载时给浏览器一些喘息的空间。

var nextRow = 0;
var handler;


//Process a row in every 250ms
var handler = setInterval(function() {

   //Select next row
   var row =arr[nextRow];

   var res= "<div class='tr' idattachment='" + row["IdAttachment"] + "' >" +
            "<div class='td colTitle'>" + row["Title"] + "</div>" +
            "<div class='td colLink'>" + row["Name"] + "</div>" +
            "<div class='td colSize'>" + (row["Size"] / (1024 * 1024)).toFixed(2) + "</div>" +
            "<div class='td colUploadDate'>" + row["UploadDate"] + "</div>" +
            "<div class='td colOpen'><a class='link' href='uploads/" + row["Name"] + "'>Open</a></div>" +
            "</div>";

   //Append
   $(".tbody").appendChild(res);

   //Move on
   nextRow++;

   //Exit at the end
   if (arr.length === nextRow)
      clearInterval(handler);

}, 250);

这将一直将数据添加到表中。

还请记住,字符串连接是昂贵的。您甚至可以在没有间隔的情况下尝试使用appendChild方法。