Pre-brief
This is the first part of an intended series into Vue, with the intention for myself to dive a bit deeper into Vue.js. I’m merely writing this for my own good, to better understand Vue, and to have something to write about.
The Vue lifecycle hooks and background
Every Vue component needs to be initialized before it is created, and these steps are called lifecycle hooks. The idea behind these hooks are to set up everything that the component needs, such as compiling the Vue template into JavaScript and render functions. 1
A Vue template is written in HTML-syntax, that may look like this:
<div>
<h1>{{ title }}</h1>
<p v-if="isDescriptionShown">This is a description.</p>
</div>
The Vue compiler processes this and transforms it into JavaScript, that looks like this:
function render() {
return h('div', [
h('h1', title),
isDescriptionShown ? h('p', 'This is a deep dive into Vue.') : null
]);
}
h
is a helper function that creates Virtual DOM (vDOM) nodes.
What is the Virtual DOM?
Applications are becoming more complex, which introduced the Virtual DOM, a lightweight copy of the real DOM. In Vue, this is the rendering process that the whole framework relies on for rendering. The vDOM is a representation of the DOM and syncs with it. 2 3
This means that we build the site using several vnode
s. Our example above would look something like this as a vnode
:
const data = {
title: "Welcome to Concentration Code",
isDescriptionShown: true,
};
const vnode = {
type: 'div',
children: [
{
type: 'h1',
children: [
{
type: 'text',
value: data.title,
},
],
},
data.isDescriptionShown
? {
type: 'p',
children: [
{
type: 'text',
value: 'This is a deep dive into Vue.',
},
],
}
: null,
],
};
The interesting part here is that we can already see how Vue implements the v-if
. If isDescriptionShown
is false
, then the last child would be null
. When the application or component is mounted, the renderer goes through the virtual DOM and constructs the real DOM from it, or if there are two versions of it, then it compares the vDOMs and makes changes to the real DOM.
According to Vue, other implementations of vDOM has to traverse the whole tree to determine changes, while Vue has implemented Compiler-Informed Virtual DOM, which supposedly makes Vue faster since it controls both the runtime and compiler. For example, if the nodes only contain static code, and not dynamic like the {{ title }}
above, then the Vue vDOM does not have to inspect and recreate it, since it cannot change.
The first lifecycle hook: setup
Note: Composition API only
In the Options API, if we want to declare reactive state like ref
and expose it to the template, we need to do it within the setup
hook. 4
For example, if we want to declare a reactive title for the above template, we could do it like this:
<script>
import { ref } from 'vue'
export default {
setup() {
const title = ref('This is my title')
return {
title
}
},
mounted() {
console.log(this.title)
}
}
</script>
Since the setup
hook is run before mounted
, it is available to the component already in that hook. In Vue3, to access a ref
value, we need to use .value
, e.g. title.value
, however, for Options API components this is not the case.
One important note: It’s possible to access props within setup, like this:
<script>
setup(props) {
console.log(props)
}
</script>
However, according to Vue, it’s important that you use props like props.x, and not destructure them, since props lose their reactivity if destructured.
✅ Do:
<script>
setup(props) {
const { isDescriptionShown } = toRefs(props)
const isDescriptionShown = toRef(props)
return {
isDescriptionShown
}
}
</script>
❌ Don’t:
<script>
setup(props) {
const { isDescriptionShown } = props
return {
isDescriptionShown
}
}
</script>
Setup also contains another argument, which exposes Context: attrs
, emit
, slots
, and expose
.
A note on expose
If you’re testing things in Vue 3, you may want to expose most of your variables for tests to work.
Wrap-up
We’ve gone through Vue’s Virtual DOM, a bit about the lifecycle hooks, and introduced the first hook: setup
.