Creation Hooks
Learn and practice the hooks related to object creation—beforeCreate and created.
We'll cover the following
The first two lifecycle hooks we’re going to look at are coincidentally the first ones that get executed whenever a component initializes—beforeCreate
and created
. Every component, and even the Vue app itself, knows these. Let’s look at the diagram below to understand the context of these hooks:
Notice that when these two hooks get executed, neither the template nor any reactivity is around—so what exactly is the use of these two hooks?
We’ll answer this question later in the lesson. However, we first need to know how we can add these hooks to use them.
Adding the hooks
Adding lifecycle hooks is straightforward. Unlike methods, computed fields, props, or data, they don’t live in their own category. They’re not nested in an extra object but directly live in the component’s object. We describe hooks as single functions that don’t take any arguments. We can define them on any Vue instance, either a Vue app or a single Vue component.
import { createApp } from 'vue'createApp({// data() { ... },// computed: ...,// methods: ...,beforeCreate() {console.log('Hello from beforeCreate in app')},created() {console.log('Hello from created in app')}})
Notice that we also added the data
, computed
, and methods
keys to illustrate where lifecycle hooks live. An alternative syntax is to define them as object keys and use anonymous functions or arrow functions instead, as illustrated below:
import { createApp } from 'vue'createApp({// data() { ... },// computed: ...,// methods: ...,beforeCreate: function() {console.log('Hello from beforeCreate in app')},created: () => {console.log('Hello from created in app')}})
We can also add them the very same way in a single-file component, as illustrated below:
<template><!-- ... --></template><script>export default {beforeCreate() {console.log('Hello from beforeCreate in component')},created() {console.log('Hello from created in component')}}</script>
Note: Generally, it’s considered good practice to add the hooks in the order of their execution after the methods. This way, we always know where to look for them and don’t confuse them with any other part of the component.
Examining the hooks
Now that we know how to add the hooks, we can examine them. Let’s build a basic Vue app that does nothing but execute these two hooks. First, we’ll look at things like data
, computed
, and some instance properties, such as $el
, to understand which items are available.
We can click “Run” further down to execute the code. Feel free to experiment for a bit! You should think about the following questions as you do so: What things are there and what aren’t? Is it possible to do anything with the Vue app in these hooks? What happens when we overwrite parts of the app in the hooks?
import { createApp } from 'vue' const app = createApp({ render() { return 'Open your browser dev tools to inspect.' }, data() { return { message: 'Hello!' } }, computed: { result() { return 2 + 2 } }, beforeCreate() { console.log('beforeCreate:') console.log('Hook arguments: ' + JSON.stringify(arguments)) console.log('this: ' + typeof this) console.log('this.message: ' + typeof this.message) console.log('this.result: ' + typeof this.result) console.log('this.$el: ' + typeof this.$el) }, created() { console.log('<h2>created:</h2>') console.log('Hook arguments: ' + JSON.stringify(arguments)) console.log('this: ' + typeof this) console.log('this.message: ' + typeof this.message) console.log('this.result: ' + typeof this.result) console.log('this.$el: ' + typeof this.$el) } }) app.mount('#app')
We might notice a few things:
- First of all,
this
is always around. The Vue component has been initialized, at least on a class level. - Both
data
andcomputed
are not around atbeforeCreate
but show up oncecreated
is called. They need to be initialized in between. $el
is not around, even atcreated
. This must have to do with templating.- None of these hooks have arguments.
Now, how can we leverage this?
Use cases
Generally, we can’t do very much in these two hooks, especially in beforeCreate
. These hooks help debug and do Vue-agnostic work upfront though. For example, we can trigger API calls very early on. We can store the promises outside the Vue component and attach them to the component’s data
later on.
We’ve prepared a backend that offers an API that returns five random poems, including some metadata, as JSON objects. So let’s say we want to fetch these as early as possible and not block any setup of Vue, essentially making the initial setup feel faster.
Let’s see if we can use beforeCreate
and created
to fetch poems as early as possible and assign them to the data
in App.vue
. Also, add a loading message to App.vue
to let the user know that there was no error, and the App fetches the content. Now, try fetching the poems in an async-computed property. Is there a noticeable drop in performance?
<template> <div> Loaded {{ poems.length }} poems <div v-for="(poem, index) in poems" :key="index"> <h2>{{ poem.title }}</h2> <p>{{ poem.content }}</p> <p>by {{ poem.poet.name }}</p> </div> </div> </template> <script> export default { props: { poems: { type: Array, required: true } } } </script>
In the hint below, we can find a solution for the above problem.
These hooks are pretty helpful for upfront work and speed up the setup of an app. To make an app respond faster, shifting things like data fetching or state negotiation to a time as early as possible is very useful.