使用 JavaScript 更新 html 方法的主体

Moh*_*alo 2 html javascript html-table

我正在尝试使用 javascript 更新 html 表的主体。

有两种方法可以做到这一点

html表:

    <table>
     <thead>
      <tr>
        <th>Title</th>
      </tr>
     </thead>
     <tbody>
     </tbody>
    </table>
Run Code Online (Sandbox Code Playgroud)

方法一(字符串插值):

    document.querySelector('table tbody').innerHTML= 
    '<tr><td>some text</td></tr><tr><td>some text</td></tr>'

Run Code Online (Sandbox Code Playgroud)

方法二:

    const table = document.querySelector("table");
    const row = table.insertRow(0);
    const cell1 = row.insertCell(0);
    cell1.innerHTML = 'some text';
Run Code Online (Sandbox Code Playgroud)

哪种方法具有更好的性能,为什么?

假设每 1 秒我们必须更新表的整个主体,并且我们有 100 行

注意:我只想了解性能并忽略安全等其他问题

zer*_*0ne 5

尽可能避免更改 DOM

作为前端开发人员,我们处理的最消耗资源的操作之一是对 DOM 的更改。回流和重绘涉及浏览器必须处理的大量计算,因此应尽量减少对 DOM 的交互和更改。我们可以使用 adocumentFragment作为构建的临时文档来添加、删除和修改 HTML 和文本。docFrag 不附加到 DOM,因此对 docFrag 执行的任何操作都不会影响 DOM。

测试 A测试 B中,所有操作都在 docFrag 上完成——每个测试 DOM 将进行 2 次重绘和 2 次回流。为了充分了解回流和重绘的危害性,请访问此测试套件。其中有 4 个测试用例TEST ATEST B与此答案中提供的堆栈片段相同 - TEST C是没有 docFrag 的TEST A , TEST D是没有 docFrag 的TEST B。至于TEST C/D触发了多少次回流/重绘,我没有费心去计算(我们可以放心地假设,远远多于微不足道的 2 个TEST A/B触发的次数)。

注意:所有测试(SnippetsBenches)都具有相同的数据输入,由 100 行 3 列的多维数组组成,每个单元格的内容都是 3 位数字。

JSBench.Me - 测试 A/B/C/D

最终获胜者是...

测试A占主导地位

测试A

documentFragment和 HTMLTableElement 方法

const data=[[591,917,494],[198,200,592],[319,593,343],[149,708,760],[289,132,762],[966,587,225],[921,510,888],[175,283,918],[944,852,330],[537,518,558],[896,927,461],[324,360,719],[800,421,524],[634,868,548],[182,340,239],[636,760,786],[860,744,616],[213,512,587],[274,236,190],[861,996,552],[761,649,814],[121,471,554],[385,538,813],[802,522,861],[468,479,870],[209,238,180],[210,314,782],[682,581,644],[996,375,580],[635,586,252],[538,640,141],[650,788,716],[654,666,578],[583,573,787],[948,968,708],[993,177,355],[404,187,596],[275,312,556],[820,481,133],[598,541,618],[424,574,753],[271,257,560],[294,246,553],[240,698,833],[860,597,219],[796,295,378],[497,834,902],[168,647,239],[745,988,788],[572,356,490],[274,957,519],[698,402,673],[798,522,743],[595,677,416],[369,786,154],[691,424,502],[465,820,533],[827,966,761],[297,947,385],[817,930,803],[609,567,369],[223,981,890],[275,387,404],[407,578,779],[713,595,428],[499,986,421],[241,310,591],[713,328,239],[152,949,826],[438,840,708],[478,114,571],[274,304,105],[239,253,916],[573,281,263],[179,502,936],[725,639,245],[467,542,488],[515,923,784],[464,258,573],[582,709,761],[138,734,836],[376,572,680],[361,478,709],[924,683,538],[379,677,378],[435,850,167],[950,546,976],[236,724,194],[314,525,639],[362,715,573],[320,965,799],[973,717,627],[122,856,371],[169,702,269],[580,826,127],[949,530,791],[625,845,701],[748,570,277],[669,955,453],[279,239,867]];

const T = document.querySelector("table");

const genData = (table, tArray) => {
  let R = tArray.length;
  let C = tArray[0].length;
  const tB = document.createElement("tbody");
  const frag = document.createDocumentFragment();
  
  for (let r=0; r < R; r++) {
    let row = tB.insertRow();
    for (let c=0; c < C; c++) {
      row.insertCell().textContent = tArray[r][c];
    }
  }
  table.tBodies[0].remove(); // 1 reflow 1 repaint
  frag.append(tB);
  table.append(frag); // 1 reflow 1 repaint
}

genData(T, data);
Run Code Online (Sandbox Code Playgroud)
<table>
  <thead>
    <tr>
      <th>A</th>
      <th>B</th>
      <th>C</th>
    </tr>
  </thead>
  <tbody></tbody>
</table>
Run Code Online (Sandbox Code Playgroud)

测试B

documentFragment和渲染 HTML

const data=[[591,917,494],[198,200,592],[319,593,343],[149,708,760],[289,132,762],[966,587,225],[921,510,888],[175,283,918],[944,852,330],[537,518,558],[896,927,461],[324,360,719],[800,421,524],[634,868,548],[182,340,239],[636,760,786],[860,744,616],[213,512,587],[274,236,190],[861,996,552],[761,649,814],[121,471,554],[385,538,813],[802,522,861],[468,479,870],[209,238,180],[210,314,782],[682,581,644],[996,375,580],[635,586,252],[538,640,141],[650,788,716],[654,666,578],[583,573,787],[948,968,708],[993,177,355],[404,187,596],[275,312,556],[820,481,133],[598,541,618],[424,574,753],[271,257,560],[294,246,553],[240,698,833],[860,597,219],[796,295,378],[497,834,902],[168,647,239],[745,988,788],[572,356,490],[274,957,519],[698,402,673],[798,522,743],[595,677,416],[369,786,154],[691,424,502],[465,820,533],[827,966,761],[297,947,385],[817,930,803],[609,567,369],[223,981,890],[275,387,404],[407,578,779],[713,595,428],[499,986,421],[241,310,591],[713,328,239],[152,949,826],[438,840,708],[478,114,571],[274,304,105],[239,253,916],[573,281,263],[179,502,936],[725,639,245],[467,542,488],[515,923,784],[464,258,573],[582,709,761],[138,734,836],[376,572,680],[361,478,709],[924,683,538],[379,677,378],[435,850,167],[950,546,976],[236,724,194],[314,525,639],[362,715,573],[320,965,799],[973,717,627],[122,856,371],[169,702,269],[580,826,127],[949,530,791],[625,845,701],[748,570,277],[669,955,453],[279,239,867]];

const T = document.querySelector("table");

const genData = (table, tArray) => {
  
  let R = tArray.length;
  let C = tArray[0].length;
  const tB = document.createElement("tbody");
  const frag = document.createDocumentFragment();
  
  for (let r=0; r < R; r++) {
    tB.innerHTML += `<tr></tr>`;
    for (let c=0; c < C; c++) {
      tB.rows[r].innerHTML += `<td>${tArray[r][c]}</td>`;
    }
  }
  table.tBodies[0].remove(); // 1 reflow 1 repaint
  frag.append(tB);
  table.append(frag); // 1 reflow 1 repaint
}

genData(T, data);
Run Code Online (Sandbox Code Playgroud)
<table>
  <thead>
    <tr><th>A</th><th>B</th><th>C</th></tr>
  </thead>
  <tbody></tbody>
</table>
Run Code Online (Sandbox Code Playgroud)