This is the second part of a series called Create Your Own Vue.js From Scratch, where I teach you how to create the fundamentals of a reactive framework such as Vue.js. In the first part, I described the pieces we need and the road map to follow. If you haven't read it, I suggest you do that before reading this post.
I only have 1 year of professional experience working with Vue.js, but I attended an 8-hour course given by Evan You himself (as part of Vue.js Amsterdam where I learned how Vue.js works on the inside and made me really understand how the "magic" behind the scenes works. This blog series is meant to teach everyone who is interested what I learned on that fantastic workshop, in a comprehensive way.
Roadmap 🚘
- Introduction
- Virtual DOM basics (this post)
- Implementing the virtual DOM & rendering
- Building reactivity
- Bringing it all together
What is a virtual DOM?
💡 DOM = Document Object Model, the HTML structure of a website 💡 VDOM = Representative copy of that structure
A virtual DOM is a representation of the real DOM into a JavaScript format, where it's easier and cheaper to manipulate it than manipulating the real DOM every time something changes.
It's also useful if you don't want to render the DOm to the browser, but to a string for instance (handy when it comes to server-side rendering).
Virtual nodes
So, the virtual DOM is composed of virtual nodes, which in the example we're going to code will look something like this:
{
tag: 'div',
props: {
class: 'container'
},
children: [
{
tag: 'h1',
props: {},
children: 'Hello World'
},
{
tag: 'p',
props: {},
children: 'Lorem ipsum dolor sit amet.'
}
]
}
The example above is the equivalent to this HTML code:
<div class="container">
<h1>Hello World</h1>
<p>Lorem ipsum dolor sit amet.</p>
</div>
So all a virtual node is composed of is:
- An HTML tag as String
- An Object of properties
- A list of children than can either be:
- Another node
- A text (representing the content)
Virtual DOM skeleton
In our example, we will not build a full-fledged virtual DOM "engine", but enough to understand the basics.
Let's take a look at the coding of the virtual DOM. We will base all future code on the following lines. So, create an HTML-file with the following content:
<div id="app"></app>
<script>
// Create virtual node
function h(tag, props, children) {
// Return the virtual node
}
// Mount a virtual node to the DOM
function mount(vnode, container) {
// Create the element
// Set props
// Handle children
// Mount to the DOM
}
// Unmount a virtual node from the DOM
function unmount(vnode) {
// Unmount the virtual node
}
// Take 2 vnodes, compare & figure out what's the difference
function patch(n1, n2) {
// Case where the nodes are of the same tag
// Case where the new vnode has string children
// Case where the new vnode has an array of vnodes
// Case where the nodes are of different tags
}
function render(message) {
// Render a virtual node with a given message
}
// Create virtual nodes & render them below this line...
</script>
As you can see, we have five different functions which all do their part to create and render a virtual DOM:
-
h
creates a virtual node (but does not mount it yet to the real DOM). I called thish
, because that's how it is called in the Vue.js project as well -
mount
will take a given virtual node and mount it to a given container in the real DOM. For the first element, this will be the#app
node we created at the very top of the file. -
unmount
will remove the virtual node from it's parent node -
patch
is by far the biggest function we will write for the VDOM. This is, because we have to compare two different nodes and check all the differences in a recursive manner (doing it for all the children recursively). -
render
is a simplified version of a render function. In our example, it creates various virtual nodes with a given the message inside (which we later change to demonstrate our VDOM "engine" works.
What's next ⚡️
In part 1, we saw the building parts we'll need for building our own Vue.js-like framework and in this part, we saw the basics of how we are going to build the virtual dom.
In the next chapter, we will then actually implement the complete virtual DOM part.
Stay tuned 😉
If you like my content and updates, your best bet would be to follow me on Twitter. That's where I usually hang out under the handle @_marcba
Original cover photo by Joshua Earle on Unplash, edited by Marc Backes.
Top comments (2)
I have a few questions:
unmount
shouldn't unmount traverse the tree and remove from leaf upwards?
i believe that only removing the root of the trunk could cause DOM leaks, but i might be wrong so please correct me
patch
You are only patching when the children length is different.
But what if the children changed, but the count is the same? Is it a real scenario?
There is a typo on the #app div, you are closing it with
</app>
should be</div>
Great guide, thanks a lot!