'Updating page elements with JS efficiently
I am making a game and using hundreds of lines of
document.getElementById("ID").innerHTML = someVariable;
to update everything I calculated with functions. How could I make it better or is this the best method? I can't really use loops for it like
for (var i = 0; i < IDs.length; i++) {
document.getElementById("IDs[i]").innerHTML = Variables[i];
}
beacuse I have so much different variables and diferent ids.
So should I rework everything into arrays and use them or what?
Thanks for any advice!
Solution 1:[1]
There are several things that you might do improve performance a little. Unfortunately jsperf is down for maintenance at the moment, but I'm not sure that it would help much because the efficiency of DOM manipulations varies so widely between browsers and the particulars of an application.
The first thing I would suggest is a set of "micro efficiencies" which may not even help much but are good practice nonetheless. Keep an array of references to your DOM elements so you don't have to call getElementById
often. While getElementById
is very fast, it is still a function call which can be avoided. You might think that the array will take up a lot of memory, but you aren't actually storing the DOM elements in the array but rather storing pointers to DOM elements. Also, you can also keep a reference to the length
of items so that it's not calculated on every loop iteration:
const myDivs = [/* populate this array with your DOM elements */];
for (var i = 0, l = IDs.length; i < l; i++) {
myDivs[i].innerHTML = Variables[i];
}
Another thing which is important is to wait for an animation frame before doing a heavy DOM manipulation. You can read more about requestAnimationFrame here.
Finally, you are just going to have to test. As someone suggested in a comment your best bet is to do direct DOM manipulation without using innerHTML
. The reason for this is because innerHTML
requires parsing and render tree construction which is expensive. An example of direct DOM manipulation would be... let's say you want to go from this state:
<div id="ID[1]">
<img src="foo.jpg" />
</div>
... to this state:
<div id="ID[1]">
<h1>Hello</h1>
<img src="foo.jpg" />
</div>
We just added an H1 - you would write something like this:
const h1 = document.createElement('h1');
h1.innerText = 'Hello';
const div = document.getElementById('ID[1]');
div.insertBefore(h1, div.firstChild);
But as you can see, this requires you to do a "diff" between the before and after states and calculate the most efficient way to get from one to the other. It just so happens that this is what ReactJS and other Virtual DOM libraries do very efficiently - so you might try out one of those libraries.
If you are against using a library or think that your DOM will fluctuate too much for in-memory diffing to be efficient, then you might try constructing a DOM string and using innerHTML as few times as possible. For example, if your DOM looks like this:
<div id="main-container">
<div id="ID[1]">...</div>
<div id="ID[2]">...</div>
<div id="ID[3]">...</div>
...
</div>
Then try doing something like the following:
let html = '';
const container = document.getElementById('main-container');
for (let i = 0, l = IDs.length; i < l; i++) {
html += `<div id="ID[${i}]">${Variables[i]}</div>`;
}
// you want to set innerHTML as few times as possible
container.innerHTML = html;
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |