Home > Software design >  Update the body of html method using JavaScript
Update the body of html method using JavaScript

Time:12-25

I am trying to update the body of html table using javascript.

There are two methods to do that

html table:

    <table>
     <thead>
      <tr>
        <th>Title</th>
      </tr>
     </thead>
     <tbody>
     </tbody>
    </table>

Method1(string interpolation):

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

Method2:

    const table = document.querySelector("table");
    const row = table.insertRow(0);
    const cell1 = row.insertCell(0);
    cell1.innerHTML = 'some text';

Which method has a better performance and why?

Suppose that every 1 second we have to update the entire body of the table and we have 100 rows

Note: I only want to know about performance and ignore other concerns like security

CodePudding user response:

Let's test the performance with 1000 runs of table body updates. To compare apples to apples, both methods replace the whole table with 100 rows with each run:

function method1() {
  // add 100 rows:
  document.querySelector('#method1 tbody').innerHTML = '<tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr> <tr><td>some text</td></tr>';
}

function method2() {
  const tbody = document.querySelector('#method2 tbody');
  tbody.innerHTML = '';
  // add 100 rows:
  for(let i = 1; i <= 100; i  ) {
    tbody.insertRow(0).insertCell(0).innerHTML = `row ${i} text`;
  }
}

let start = new Date();
for(let i = 0; i < 1000; i  ) {
  method1();
}
let end = new Date();
console.log('method1:', end - start, 'ms');

start = new Date();
for(let i = 0; i < 1000; i  ) {
  method2();
}
end = new Date();
console.log('method2:', end - start, 'ms');
<table id="method1">
 <thead>
  <tr>
    <th>Method 1</th>
  </tr>
 </thead>
 <tbody>
 </tbody>
</table>
<table id="method2">
 <thead>
  <tr>
    <th>Method 2</th>
  </tr>
 </thead>
 <tbody>
 </tbody>
</table>

Console log:

method1: 178 ms
method2: 463 ms

As suspected, method1 is 2.5x faster than method2. This makes sense, because to replace the tbody in method2 you need to empty it out first, and you have 200 method calls instead of a single update.

CodePudding user response:

Avoid Changing the DOM as Much as Possible

One of the most resource sapping operations we as front end developers deal with are changes to the DOM. Reflows and repaints involve a ton of computations the browser must deal with so keep interactions and changes to the DOM to a minimum. We can add, remove, and modify HTML and text by using a documentFragment as a temporary document to build upon. a docFrag isn't attached to the DOM so any operations done on the docFrag does not affect the DOM.

In Test A and Test B all operations are done on a docFrag -- the DOM will have 2 repaints and 2 reflows per test. In order to fully appreciate how detrimental reflows and repaints are, go to this test suite. Therein are 4 test cases TEST A and TEST B are the same as the Stack Snippets provided in this answer -- TEST C is TEST A without a docFrag and TEST D is TEST B without a docFrag. As for how many reflow/repaints does TEST C/D trigger I didn't bother to count (we can safely assume far more than a paltry 2 TEST A/B does).

Note: all tests (Snippets and Benches) have the same data input consisting of a multidimensional array of 100 rows and 3 columns and each cell's content is a 3 digit number.

JSBench.Me - TEST A/B/C/D

And the winner is...

TEST A dominated

  • Related