(A Complete Guide to Vue Lifecycle Hooks in Vue3 — LearnVue)

Vue3 has a very similar lifecycle hooks to Vue2 — we can still use the same hooks (or similar hooks) in the same scenario.

If the project is built using the Options API, there is no need to modify any life-cycle code. This is because Vue3 was designed to be compatible with previous versions.

However, if you build your project using the Composition API approach, which is useful when building large Vue projects, the lifecycle hooks are slightly different.

By reading this article, you’ll learn how to use lifecycle hooks in the Options API and Composition API and let you write better code.

Blunt!

What are Vue lifecycle hooks

First, let’s take a look at the Vue3 lifecycle hook diagram for the Options API and Composition API. Before we get into that, we can get the overall picture.

Basically, each main Vue lifecycle event corresponds to two hook functions, one called before the event starts and one called after the event ends. There are four main events that you can apply in the Vue app (eight main hooks functions).

  • Creation – Run when the component is created
  • Mounting – Run while Mounting the DOM
  • Updates – Run in response to data changes
  • Destruction — Runs before the element is destroyed

Use lifecycle hooks in the Options API

When using the Options API, the lifecycle hooks are exposed in the Options of the Vue instance. We don’t need to import anything, just call the corresponding function and write the relevant lifecycle code.

For example, suppose we wanted to access the Mounted () and updated() lifecycle hooks, the code might look like this:

<script> export default { mounted() { console.log('mounted! ') }, updated() { console.log('updated! ') } } </script>Copy the code

Is it very simple?

So, let’s continue using Vue3’s lifecycle hooks in the Composition API.

Use lifecycle hooks in the Composition API

In the Composition API, we need to import the corresponding lifecycle hook first to use it. This was done to make our project as lightweight as possible.

import { onMounted } from 'vue'
Copy the code

In addition to beforeCreate and created (which are replaced by the setup method itself), there are nine Options API lifecycle corresponding methods that can be used in setup.

  • OnBeforeMount — called before mounting begins
  • OnMount — called after mounting
  • OnBeforeUpdate – called when the response data changes and before rerendering
  • OnUpdated — Called after rerendering
  • OnBeforeUnmount — called before Vue instance destruction
  • OnUnmounted – called after the instance is destroyed
  • OnActivated — called when the keep-alive component is activated
  • OnDeactivated — called when the keep-alive component is deactivated
  • OnErrorCaptured – called when an error is captured from a child component

When we need to import and access these hook functions, the code might look like this:

<script> import { onMounted } from 'vue' export default { setup () { onMounted(() => { console.log('mounted in the composition api! ') }) } } </script>Copy the code

Update the Vue2 code to a Vue3 lifecycle hook

You can easily view the Vue2 to Vue3 lifecycle mapping in the Vue3 Composition API Docs. And I think it’s one of the most effective ways to figure out how to change and use them.

  • beforeCreate -> setup()
  • created -> setup()
  • beforeMount -> onBeforeMount
  • mounted -> onMounted
  • beforeUpdate -> onBeforeUpdate
  • updated -> onUpdated
  • beforeDestroy -> onBeforeUnmount
  • destroyed -> onUnmounted
  • errorCaptured -> onErrorCaptured

Learn more about each lifecycle hook

Now we know two important things:

  1. We can use various life cycles
  2. How do I use them in the Options API and Composition API

Next, let’s dive into each lifecycle hook, learn how to use them, what code can be written in each hook, and talk about the differences between the Options API and Composition API.

Creation hook — The beginning of the VueJS lifecycle

The Creation hook is the first event that fires when you start a project.

BeforeCreate () – the Options API

Because created hooks are used to initialize response data and events, you cannot access any component’s response data and events in the beforeCreate hook.

Take a look at the following code example:

export default {
   data() { 
     return { 
       val: 'hello'}},beforeCreate() {     
     console.log('Value of val is: ' + this.val)   
   }
}
Copy the code

Since the data is not initialized at this point, the value of val is undefined, and you cannot call other methods in the component from this function.

If you want to see a list of properties you can use, I recommend using console.log(this) to see which properties have already been initialized. This is also true for the other hook functions of the Options API.

BeforeCreate is useful for logical and API calls that do not need to allocate data. If we assign values to data at this point, those values will be lost after the state is initialized.

Created () – the Options API

At this point, we have access to the component’s data and events. Therefore, by replacing beforeCreate with created in the previous example, we can see some changes in the output.

export default {
   data() { 
     return { 
       val: 'hello'}},created() {     
     console.log('Value of val is: ' + this.val)   
   }
}
Copy the code

Since this is already initialized, the above example prints Value of val is: hello.

The Created method is useful when you need to deal with reactive data reading/writing. For example, if you need to complete an API call and store its value, you should write it here.

This is better than handling in Mounted because it fires earlier in Vue initialization and you can read and write all data.

What about the Creation hook for the Composition API?

In the lifecycle hooks of the Composition API, beforeCreate and Created are replaced by the setup() method. This means that you should write the corresponding code in the setup method.

Rewrite the just created lifecycle hook as shown below

import { ref } from 'vue'

export default {
   setup() {    
     const val = ref('hello') 
     console.log('Value of val is: ' + val.value)       
     return {         
       val
     }
   }
}
Copy the code

Mounting Hook – Access the DOM

Mounting the Mounting hook handles mounting and rendering components. This is the most common set of hooks we use in projects and applications.

beforeMount() and onBeforeMount()

Triggered before the component DOM is actually rendered and mounted. At this stage, the root element does not yet exist. In the Options API, this.$el is accessible. In the Composition API, you must specify the root element by ref.

export default {
   beforeMount() {
     console.log(this.$el)
   }
 }
Copy the code

The Composition code might look like this:

<template>
   <div ref='root'>
     Hello World
   </div>
</template> 
Copy the code

The script code accessed from ref is as follows:

import { ref, onBeforeMount } from 'vue'

export default {
   setup() {
      const root = ref(null) 
      onBeforeMount(() = > {   
         console.log(root.value) 
      }) 
      return { 
         root
      }
    },
    beforeMount() {
      console.log(this.$el)
    }
 }
Copy the code

Because app.$el has not yet been created, the output from the above code will be undefined.

In the meantime, we recommend executing your API calls in created() and setup. Both have the same component variable access, but beforeMount is called after Created.

mounted() and onMounted()

Called when the component is first rendered. At this point, the component has access to the DOM.

Similarly, in the Options API we use this.$el to access our DOM, and in the Composition API lifecycle hooks we need refs to access the DOM.

import { ref, onMounted } from 'vue'
 

 export default {
   setup() {    /* Composition API */
 
     const root = ref(null)
 
     onMounted(() = > {
       console.log(root.value)
     })
 

     return {
       root
     }
   },
   mounted() { /* Options API */
     console.log(this.$el)
   }
 }
Copy the code

Update hook — the response in the VueJS lifecycle

The updated life cycle event fires whenever the response data is modified and triggers a render update.

beforeUpdate() and onBeforeUpdate()

Execute before the data is modified and the component is rerendered. This is a good place to manually modify the DOM before any changes occur.

BeforeUpdate is useful for tracking the number of edits of a component and can even create an “undo” function by tracking the corresponding action.

updated() and onUpdated()

The updated method is called once after DOM updates. This is a basic piece of beforeUpdate and updated code

 <template>
    <div>
      <p>{{val}} | edited {{ count }} times</p>
      <button @click='val = Math.random(0, 100)'>Click to Change</button>
    </div>
 </template>
Copy the code

Corresponding script code

 export default {
   data() {
      return {
        val: 0}},beforeUpdate() {
      console.log("beforeUpdate() val: " + this.val)
   },
   updated() {
      console.log("updated() val: " + this.val
   }
 }
Copy the code

or

import { ref, onBeforeUpdate, onUpdated } from 'vue'
 
 export default {
   setup () {
     const count = ref(0)
     const val = ref(0)
 
     onBeforeUpdate(() = > {
       count.value++;
       console.log("beforeUpdate");
     })
 
     onUpdated(() = > {
       console.log("updated() val: " + val.value)
     })
 
     return {
       count, val
     }
   }
 } 
Copy the code

These methods are useful, but most of the time we might detect a change in the data via watchers. Listeners do a good job of providing old and new values as data changes.

Another way is to change the state of an element by evaluating its attributes.

The hook of Destruction

The Destruction hook is used when a component has been removed and needs to clean up some functionality to be released. This is a good place to remove event listeners and prevent memory overruns.

beforeUnmount() and onBeforeUnmounted()

Trigger This is where most of the cleanup takes place before the component begins its destruction. At this stage, your component still has all the functionality and nothing has been destroyed.

For an example of a deletion event listener, the Options API looks like this

export default {
   mounted() {
     console.log('mount')
     window.addEventListener('resize'.this.someMethod);
   },
   beforeUnmount() {
     console.log('unmount')
     window.removeEventListener('resize'.this.someMethod);
   },
   methods: {
      someMethod() {
         // do smth}}}Copy the code

Composition API way

 import { onMounted, onBeforeUnmount } from 'vue' 

 export default {
   setup () {
 
     const someMethod = () = > {
       // do smth
     }
 
     onMounted(() = > {
       console.log('mount')
       window.addEventListener('resize', someMethod);
     })
 
     onBeforeUnmount(() = > {
       console.log('unmount')
       window.removeEventListener('resize', someMethod); }}})Copy the code

You can view these actions in Vite, VUE-CLI, or any environment that supports hot loading. When you update the code, your component is destroyed and remounted.

unmounted() and onUnmounted()

At this point, most of the component and its properties have been destroyed, so there’s not much you can do. Again, I print a piece of data to see exactly what’s going on.

import { onUnmounted } from 'vue'

export default {
  setup () { /* Composition API */

    onUnmounted(() = > {
      console.log('unmounted')})},unmounted() { /* Options API */
    console.log('unmounted')}}Copy the code

Activation hook — Manages keep-alive components

The keep-alive tag is a wrapper around a dynamic component. It holds a cache reference to a component instance so that Vue does not need to create a new instance every time a dynamic Component changes.

For this particular use, Vue provides two lifecycle hooks.

activated() and onActivated()

This hook method is called whenever the dynamic component is “reactivated” (meaning it is the dynamic component that activates the view at this time).

For example, if we use keep-alive to manage different TAB views, each time we switch a TAB, the current TAB will trigger the Activated hook.

Suppose we have the following dynamic component setup wrapped with keep-alive.

<template> <div> <span @click='tabName = "Tab1"'>Tab 1 </span> <span @click='tabName = "Tab2"'>Tab 2</span> <keep-alive>  <component :is='tabName' class='tab-area'/> </keep-alive> </div> </template> <script> import Tab1 from './Tab1.vue' import Tab2 from './Tab2.vue' import { ref } from 'vue' export default { components: { Tab1, Tab2 }, setup () { /* Composition API */ const tabName = ref('Tab1') return { tabName } } } </script>Copy the code

In our Tab1.vue component, we can access the Activation hook as follows.

<template> <div> <h2>Tab 1</h2> <input type='text' placeholder='this content will persist! '/> </div> </template> <script> import { onActivated } from 'vue' export default { setup() { onActivated(() => { console.log('Tab 1 Activated') }) } } </script>Copy the code

deactivated() and onDeactivated()

As you might expect, this hook fires when the view does not remain active in the dynamic component.

This hook is useful in situations such as saving user data and triggering animations when a particular view loses focus.

We can capture the lifecycle hook as shown below

import { onActivated, onDeactivated } from 'vue'

export default {
  setup() {
    onActivated(() = > {
       console.log('Tab 1 Activated')
    })

    onDeactivated(() = > {
       console.log('Tab 1 Deactivated')}}}Copy the code

Now, when we switch TAB, the state of each dynamic component will be saved.

Yay!

Vue3 Debug Hooks

Vue3 provides us with two hooks for debugging:

  1. onRenderTracked
  2. onRenderTriggered

Both events carry a DebuggerEvent parameter to allow us to learn what triggered the re-rendering of the Vue instance.

export default {
    onRenderTriggered(e) {
       debugger
       // Check what dependencies cause the component to rerender}}Copy the code

conclusion

Whether you’re using the Options API or the Composition API, know not just what lifecycle you can use, but why.

Many problems can be solved in multiple lifecycle hooks. However, it’s good to know which life cycle is best for your current situation. Either way, you need to be thoughtful and have a good reason for using a particular lifecycle.

I hope this article has helped you understand lifecycle functions and apply them in your projects.

Happy coding!