Why virtual DOM?
To avoid re-creation of elements if possible in real DOM, when one manipulates DOM elements.The Virtual DOM concept can help in efficient DOM manipulation through diffing and reconciliation.
Diffing is a process of comparing the previous virtual DOM to current virtual DOM and changing only those elements which are different.
Note: List items should have a *key attribute to stop recreating the list items that aren't changed.*
Reconciliation is when virtual DOM syncs with real DOM.
Real or browser DOM looks like the one shown below:
Virtual DOM is representation of UI, like real DOM excluding the heavy parts, which is kept in memory as a javascript object.
Virtual DOM looks like the one shown below:
//virtual DOM
const virtualDOM = {
tagName: 'html',
children: [
{ tagName: 'head' },
{
tagName: 'body',
children: [
{
tagName: 'div',
attributes: { id: 'root' },
children: [
{
tagName: 'div',
attributes: { class: 'App' },
children: [
{
tagName: 'ul',
children: [
{ tagName: 'li', textContent: 'Tea' },
{ tagName: 'li', textContent: 'Juice' },
{ tagName: 'li', textContent: 'Water' },
{ tagName: 'li', textContent: 'Milk' },
],
},
],
},
],
},
],
},
],
};
Suppose there is a list of four items, and you wish to change the child of first list item, then in real DOM that list element will be recreated along with the updated text.
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
</head>
<body>
<script>
function change() {
document.getElementById("Tea").innerHTML = "Tee";
}
</script>
<div id="app">
<ul>
<li id="Tea">Tea</li>
<li id="Juice">Juice</li>
<li id="Water">Water</li>
<li id="Milk">Milk</li>
</ul>
<button id="1" onClick="change()">Change first item</button>
</div>
</body>
</html>
The purple highlighted texts in both the images shown below are recreation.
Manipulating real DOM without using virtual DOM concept
import React from "react";
export default function App() {
const [name, setName] = React.useState("Tea");
return (
<div className="App">
<ul>
<li key="Tea">{name}</li>
<li key="Juice">Juice</li>
<li key="Water">Water</li>
<li key="Milk">Milk</li>
</ul>
<button id="1" onClick={() => {
setName("Tee")
}}>Change first item</button>
</div>
);
}
If the same thing is done using virtual DOM only the changed child not the list element will be recreated in the real DOM as shown below.
Manipulating real DOM using virtual DOM concept
Top comments (14)
I think we can write a simple virtual dom function like that. This isn't best but it should work :P
Hey! Itachi uchiha
Have you tried to exceute it?
😃
I didn't. But I'm sure it will work for the first time.
When you run it secondly, probably it will create duplicate elements.
With all the respect, I think Virtual DOM will slowly start vanishing in favour of build-time DOM diffing already provided by SolidJS or Svelete. We might lie ourselves that keeping a copy of an entire DOM tree and re-calling the entire call-stack is more performant. But, the truth is that Virtual DOM is just a tool which has been used to allow declarative UI building and this can be already done without Virtual DOM.
Hey! Chris-czopp
Build-time DOM diffing sounds fascinating.
I would like to know more about this diffing, could you write a post on it or elaborate in the comments.
Thanks in advance
It has been already covered quite well, you can take a look at dev.to/t/solidjs
I am a little confused, what are we comparing React to in this post? Is this a comparison to an old framework or something as this shouldn't be true in most circumstances.
For example with vanilla JS you would just do
document.querySelector('li').remove();
to remove the first list item - that is essentially what React is doing, but after it has diffed the document to work out that is what needs doing.There is no need to repaint the whole document in any framework I have ever seen, certainly not in vanilla JS?
Hi! actually you're right, I re-read my post and got the mistake.
Thanks for pointing it out.
After having been working with ReactJS for a while, I still can't get the benefit of Virtual DOM. The biggest benefit that you mentioned on your post is about "fast update" and "partial update". But the point here is updating in real dom is fast too, and after updating on Virtual DOM, you still have to go back to Real DOM to update it. What makes Real DOM slow is that after updating, Real DOM have to re-calculate style, layout (it's called repaint to something like that if I rememeber it correctly), so does Virtual DOM somehow solves that problem? Thanks!
Hi! Even I feel the same, I didn't compare the speed of the Real DOM and the virtual DOM, I just tried to explain how virtual DOM works in react and what happens behind the scenes.
It's just that since react has virtual DOM you don't have to update the DOM manually.
"Virtual DOM is nothing but a copy of real DOM which is kept
in memory as a javascript object."
Feel bad for someone who read this.
Hi, Thinh Vu
If you don't find it correct, would you mind correcting it.
If I don't write article how would I know whether I understand it or not because then only good people like you would be able to correct me.
Thanks in advance
The incorrect part is "a copy of real DOM".
VDOM is not a copy of real DOM, is just a plain javascript object (PJSO) which contains ~30 properties (depend on libraries implementation).
Mean while DOM is a huge object which contains more than 100 properties (included browser specific properties which we don't even need to care about).
FYI, you can console.dir($0) in console window to see DOM properties.
Diffing VDOM tree is faster than the DOM due to the less amount of properties and the time to traversal PJSO tree rather than the DOM tree.
So we'll get the benefit for using VDOM to detect the change (everytime state change and it happen a lot).
It's weird when someone think that update DOM over VDOM is faster than update the DOM. It's totally wrong because we also need to update the DOM after the diffing completed.
Actually, by copy I didn't mean the exact copy of Real DOM because it's obvious if it would be an exact copy of real DOM then how it could be virtual DOM.
What I forgot to mention was "excluding the heavy parts of real DOM*.
I think you focused more on that copy thing and ignored the rest of the things like I too have mentioned about javascript object, and in the entire post, I didn't mention anywhere that Virtual DOM is faster than Real DOM.
I had already edited the post when you pointed out before you replying to me, try to be soft-spoken and humble, trust me it won't harm.
Thank you so much for that extra knowledge about console.dir($0).