使用javascript构建表格

时间:2015-12-28 22:10:59

标签: javascript html firefox html-table appendchild

我试图理解为什么在Firefox 43.0.2上使用javascript重建表需要这么长时间

我的代码的简化版本如下。 “真实”代码和简单版本都使用“publishTable()来向表中添加行。如果表格元素存在,则删除表格主体元素,创建一个新元素,向其添加大约9000行,并附加已完成的表格主体到桌子。

PublishTable在加载时运行,当用户单击“go”按钮时。因此,我希望在加载和重建时性能类似。

首次加载“真实”页面时,Firefox需要大约300ms才能构建表格[根据performance.now()]。当宣布此结果的alert()关闭时,我可以立即上下滚动页面。

但是,如果我单击“go”按钮重建表格,Firefox关闭alert()对话框后会旋转数十秒钟(或更长时间)。一个“停止脚本?”对话框可以出现多次。简单版本的行为类似。

所以:
为什么
在初始构建和重建之间的性能如此根本不同?显然可以在300ms内构建表格!我有什么可以做的吗?

进一步的观察:
IE的性能在初始加载时更差,在重建时也差。 Chrome的性能相当不错:构建或重建2秒。

如果我使用innerHTML,而不是insertRow,appendChild等,结果是相似的。

如果我移除了将桌子主体连接到桌子上的线条,则不会发生轮子旋转症状。

在“瀑布”图表中(在Firefox性能工具中),“DOM事件”占用的时间远远超过“事件处理程序”(我认为它涵盖了代码的运行时),而我不知道那意味着什么。在js停止运行和DOM事件结束之间发生了什么,这不属于其他瀑布类别之一?

DOM事件之后是短暂的时间重新计算样式,绘制时间,然后是许多“循环收集”期间的序列,然后是“增量gc”,“cc图缩减”,“循环收集”, “图形缩减”等等,持续数十秒。在一种情况下,性能调用树为“Gecko”(似乎是空闲时间)分配49秒,为“图形”分配另外25秒(并且在其中,仅仅1秒分配给publishTable())。我可以采取行动吗?

我没有合理的想法进行进一步分析,或者我如何修改js。我对表现信息的理解不够了解。 (现在,在使用IE和Chrome计时之后,我甚至不确定应该向谁解决这个问题。)

代码中是否存在根本错误?更好的餐桌建设策略?一种使用性能工具来理解问题的方法? Firefox中的一个错误? (而现在我将在服务器端做这件事。但我仍然对正在发生的事情感到好奇。)

<!DOCTYPE html>    
<html>     
<head>    
<meta charset="UTF-8">    
</head>    
<body>    
<div id='a'>    
<button type="button" disabled id="btnGo">Go</button><br />    
    <button type="button"  id="btnQ">?</button><br />    
<table id="tideTable" style="Width:40%;margin-left:auto;margin-right:auto;">    
</table>    
</div>    
<div id="b">    
hello    
</div>    
<script>    
(function() {
var mmm = ['one', 'two', 'three', "four", "five", "six", "seven"];
function publishTable() {
//  The user may run this several times, varying some parameters each time.
    var tStart = performance.now();
    var table = document.getElementById('tideTable');
//  var tableBody = table.getElementsByTagName('tbody')[0];
    var tableBody = table.tBodies[0];
    if (tableBody) {
        tableBody.parentNode.removeChild(tableBody);
        }
    showHeight();
    tableBody = document.createElement('tbody');
    for (var i=0; i < 8500; i++) {
        appendTableRow(tableBody, mmm);
        }
    table.appendChild(tableBody);
    document.getElementById("btnGo").disabled = false;
    alert("Time: " + (performance.now() - tStart) +  "ms");
    showHeight();
}

function appendTableRow(tableBody, columns) {
    var cell;
    var textNode;
    var row = tableBody.insertRow(-1);
    for (var i = 0; i < columns.length; i++) {
        cell = row.insertCell(i);
        textNode = document.createTextNode(columns[i]);
        cell.appendChild(textNode);
    }
}
    function showHeight(){
        var el = document.getElementById('b');
        var topPos = el.offsetTop;
        alert("position: " + topPos);
    }

document.getElementById("btnGo").addEventListener("click", publishTable);
document.getElementById("btnQ").addEventListener("click", showHeight);
publishTable();
})();
</script>
</body>
</html> 

3 个答案:

答案 0 :(得分:1)

我想,可能是因为在插入新项目之前删除了现有项目。您可以尝试以下方法:

  1. 如果您只是扩展表格而没有删除,请确保性能会发生什么

  2. 在插入表格之前构建表格,例如创建一个变量tableContent将行放入其中,然后将tableContent添加到表中,这应该更快,因为浏览器必须在每个插入时重新呈现页面。

  3. 我建议你考虑使用angularJS,如果你打算让表动态

答案 1 :(得分:1)

您的JS已缩小并位于CloudFront CDN中。

The first demo is async and the second demo is defer

异步

https://jsfiddle.net/zer00ne/6m9f24j5/

推迟

https://jsfiddle.net/zer00ne/fcpy9z0c/

结果

同样。

火箭加载时

142毫秒。

每次点击活动平均230毫秒。

Chrome加载时

846毫秒。

每次点击活动的平均值为930毫秒。

<script>代码置于结束</body>代码

之前

https://jsfiddle.net/zer00ne/y7mguyry/

Firefox

Crome

(function() {
  var mmm = ['one', 'two', 'three', "four", "five", "six", "seven"];

  function publishTable() {
    //  The user may run this several times, varying some parameters each time.
    var tStart = performance.now();
    var table = document.getElementById('tideTable');
    var tableBody = table.getElementsByTagName('tbody')[0];
    if (tableBody) {
      tableBody.parentNode.removeChild(tableBody);
    }
    tableBody = document.createElement('tbody');
    for (var i = 0; i < 8500; i++) {
      appendTableRow(tableBody, mmm);
    }
    table.appendChild(tableBody);
    document.getElementById("btnGo").disabled = false;
    alert("Time: " + (performance.now() - tStart) + "ms");
  }

  function appendTableRow(tableBody, columns) {
    var cell;
    var textNode;
    var row = tableBody.insertRow(-1);
    for (var i = 0; i < columns.length; i++) {
      cell = row.insertCell(i);
      textNode = document.createTextNode(columns[i]);
      cell.appendChild(textNode);
    }
  }

  document.getElementById("btnGo").addEventListener("click", publishTable);
  publishTable();
})();
<button type="button" disabled id="btnGo">
  Go</button>
<br />
<table id="tideTable" style="Width:40%;margin-left:auto;margin-right:auto;">
</table>

答案 2 :(得分:1)

我尝试换掉这条线:

var tableBody = table.getElementsByTagName('tbody')[0];

内置的getter:

var tableBody = table.tBodies[0];

这似乎可以稳定构建时间。仍然有点慢,但初始构建和重建报告几乎一致的时间。

这可能是巧合,但你可能想要搞清楚。