Before I continue I just want to say that it’s not bad practice to target the DOM. Without targeting the DOM, JavaScript wouldn’t be able to manipulate anything on your page, rendering it useless as a frontend programming language.
However, you do want to stay cautious and be very careful about when and where you’re targeting the DOM, as certain operations may noticeably affect the performance of your webpage.
Now with that said, you might be asking yourself:
"How bad can directly manipulating the DOM really get?"
REALLY REALLY MESSY especially if you're working in a team, you're adding unnecessary levels of complexity which can result to potential bugs whether it'd be from performance, testing and even refactoring.
Take this bit of code for example:
for (let i = 0; i < 10000; i++) {
const p = document.createElement("p");
document.body.appendChild(p);
}
We're generating 10,000 <p>
tags and appending each one to the <body>
of the DOM. This is highly inefficient as this code tells the DOM to update and figure out where everything goes again for 10,000 times.
A cleaner approach:
const fragment = document.createDocumentFragment();
for (let i = 0; i < 10000; i++) {
const p = document.createElement("p");
fragment.appendChild(p);
}
document.body.appendChild(fragment);
By grouping all our elements so that we append them all together we are able to drastically reduce the amount of times that the DOM needs to be modified down to one. This also reduced the total running time from 413.125ms to 12.189ms.
Fun Fact: React.js provides a VirtualDOM that creates a lightweight copy of the DOM which it keeps track of. React also tries to update the DOM as little as possible by grouping together changes.
Thanks for reading!
Top comments (4)
Or better still use innerHTML but not advisable if input is coming from the user (XSS Attacks).
Nice! I had no idea about createDocumentFragment.
Is this the same as the empty <> </> tag or fragments in React?
Well its the same thing actually, except one small difference. You could get same performance if you appended everything to some div (defined outside of loop) and then after the loop, append that div the the element you want. Only difference is that when you append fragment you wont have element holder (div in this case) after appending.
I think there are some tricks using the shadow DOM (not Reacts virtual), and tag that can also optimize this type of thing.