DEV Community

Cover image for A Guide to Understanding Vue Lifecycle Hooks
Johnny Simpson
Johnny Simpson

Posted on • Originally published at fjolt.com

A Guide to Understanding Vue Lifecycle Hooks

Like other frameworks, Vue has a number of lifecycle hooks which allow us to attach code to specific events that occur while a Vue application is being created or used - for example, when the component loads, when a component is added to the DOM, or when something is deleted.

Vue has a lot of lifecycle hooks, and what can be confusing is what each one means or does. In this guide, we'll be covering what each lifecycle hook does, and how to use them.

Prerequisites

If you are unfamiliar with Vue, you might want to check out my guide on creating your first Vue applications, before doing this one. Alternatively, you can read my guide on creating a to-do list in Vue, if you are slightly more familiar with it.

Lifecycle Hooks in Vue

The important thing to note here is that Vue has two paradigms when it comes to lifecycle hooks. One is using the Compositions API, something introduced in Vue 3, and the other is the "Options API", which is the prototypical pattern of defining Vue components. In this guide, we'll start with the Options API, and then build off that to show how things work in the compositions API.

Example of Options API

If you are unfamiliar with the Options API, it is the version of Vue that looks like the code below:

export default {
    name: 'Component Name',
    data() {
        return {
            phoneNumber: '123-123-123'
        }
    },
    mounted() {

    }
}
Enter fullscreen mode Exit fullscreen mode

Lifecycle Hooks Diagram

To understand when each lifecycle hook fires, let's look at a diagram. Below, an image depicts when each lifecycle hook fires.

Vue Lifecycle Hooks

Running a Lifecycle Hook

To run any lifecycle hook with the Options API, you can add it to your Javascript prototype. For example, if you want to use beforeCreate(), the first hook fired after a new component is detected, you could add it like this:


export default {
    name: 'Component Name',
    data() {
        return {
            someData: '123-123-123'
        }
    },
    mounted() {
        // Any code you want to fire immediately before the Options API loads up
    }
}
Enter fullscreen mode Exit fullscreen mode

Now that we've covered when the different hooks occur, let's look at what each of them do, and when they happen.

beforeCreate()

Called at the point the component is initialized. data() and computed properties are not available at this point. It is useful for calling APIs which do not adjust the data of the component. If you update data() here, it will be lost once the Options API loads up.

created()

Called after the instance has finished processing all state operations. You have access to reactive data, computed properties, methods and watchers. $el, which is where Vue stores the component HTML, is not available yet, since the DOM element is not created. If you want to fire something like an API, or update data(), you can do it here.

beforeMount()

This hook runs immediately before rendering occurs. The template has been compiled so it is stored in memory, but it has not been attached to the page yet. None of the DOM elements have been created yet. $el is still unavailable at this stage.

This is not called when doing server side rendering of a site.

mounted()

The component is mounted and shown on the page. $el is now available, so you can now access and manipulate the DOM from Vue. This will only fire after all child components are fully mounted. It's useful to use this when you want to do something to the DOM after it has loaded, like perhaps change a particular element within it.

This is not called when doing server side rendering of a site.

beforeUpdate()

Sometimes, you wil change data in your Vue component by updating it in a watcher, or by a user interaction. When you change data() or cause a re-render in your component, an update event will fire. Immediately before the re-render occurs, beforeUpdate() will fire. After this event, the component will be re-rendered and updated with the latest data. You can use this hook to access the current state of the DOM, and even update data() from it.

This is not called when doing server side rendering of a site.

updated()

After an update is fired, and the DOM has been updated to match the latest data, updated() will fire. This happens immediately after the re-render. Now if you access $el, or anything else about the DOM content, it will show the new, re-rendered version. If you have a parent component, the child component updated() is called first, followed by the parent updated() hook.

This is not called when doing server side rendering of a site.

beforeUnmount()

If a component is removed, then it becomes unmounted. Before the component is completely removed, beforeUnmount() fires. This event still has access to the DOM elements, and anything else to do with the component. This is useful in deletion events, for example, you can use this event to notify a server that a user has deleted a Node in a table, for instance. You still have access to this.$el, as well as data, watchers and methods, if you need to use them.

This is not called when doing server side rendering of a site.

unmount()

Once completely removed, the unmount() event fires. This can be used to clean up other data or event listeners, or timers to let them know that this component no longer exists on the page. You still have access to this.$el, as well as data, watchers and methods, if you need to use them.

This is not called when doing server side rendering of a site.

Using Vue Lifecycle Hooks with the Composition API

If you are used to using the Options API, the above hooks will make a lot of sense. If you've mainly used Vue 3, you may be more used to using the Composition API. The Composition API is complementary to the Options API, but we use hooks slightly differently. Let's take a look at how it works.

created() and beforeCreated() are replaced with setup()

In the compositions API, created() and beforeCreated() are not accessible. Instead, they are replaced with setup(). This makes sense, since there is no 'Options API' to load. Any code you would have put in created() or beforeCreated(), can now safely go in setup()

Hooks can be used alongside setup()

Hooks can still be used alongside setup, in the same way they are in the Options API, and this is pretty intuitive. For example:

export default {
    data() {
        return {
            msg: 1
        }
    },
    setup() {
        console.log('Component setup complete')
    },
    mounted() {
        console.log(this.$el)
    },
}
Enter fullscreen mode Exit fullscreen mode

However, another way you may see this done is by defining the hooks within the setup() function itself, using composition API functions. If we do things this way, the hooks are named slightly differently:

  • beforeMount() becomes onBeforeMount()
  • mounted() becomes onMounted()
  • beforeUpdate() becomes onBeforeUpdate()
  • updated() becomes onUpdated()
  • beforeUnmount() becomes onBeforeUnmount()
  • unmounted() becomes onUnmounted()

These functions do exactly the same thing as I described in the previous section, but they are called slightly differently. All of these hooks must be called within either the setup() function, or in a setup script. For example you must either run your hooks within a setup function like this:

export default {
    setup() {
        // All hooks must go here
    }
}
Enter fullscreen mode Exit fullscreen mode

Or alternatively, within a script tag with the setup attribute like so:

<script setup>
// All hooks must go within this setup script
</script>
Enter fullscreen mode Exit fullscreen mode

As such, if you want to call hooks using this methodology, your code will look like this instead:

export default {
    setup() {
        // All hooks must go here
        onBeforeMount(() => {
            // Code for beforeMount()
        });
        onBeforeUpdate(() => {
            // Code for beforeUpdate()
        })
    }
}
Enter fullscreen mode Exit fullscreen mode

There is no fundamental performance improvement, or reason why this is better. It is just another way of doing it - and in some cases it'll make your code easier to read and maintain. For other instances, you might be better off using the Options API, so use whichever you feel more comfortable with.

Conclusion

The Vue Lifecycle is quite complicated, but it gives us a lot of tools to run code, update data, and make sure our components display the way we want them to. In this guide, we've covered how it works, when to use each part of the lifecycle, and how the Compositions API works a little differently from the Options API in regards to lifecycle hooks.

If you've enjoyed this, you might enjoy some of my other Vue content. Here are some relevant links:

Discussion (0)