DEV Community

Samuel Tope
Samuel Tope

Posted on • Originally published at Medium on

Understanding Vuejs Lifecycle hooks

A component in Vuejs has a lifecycle which is being managed by Vue itself when it creates the component, mounts the component to the DOM, updates the component and destroy the components. In order words, Each component has what is known as lifecycle events — its birth, life events like changes and death_._ We can tap into key moments in that lifecycle by implementing one or more lifecycle hooks that gets called by Vue itself thereby giving us the opportunity to add our own code at specific stages of a component lifetime.

Vue has eight lifecycle hooks, and the key to remembering them is to know that four of them are event that get triggered indicating that the actual event will happen. They start with “before” prior to the actual hooks and are fired before the actual hooks.

Lets see these hooks in action.

beforeCreate  — This is the first hook that gets called after the Vue instance has been initialized. At this stage, data observation (reactivity), events, computed properties and watchers are yet to be set up. Therefore , we cannot interact with any parts of the component.

<script>
export default {
  data() {
    return {
      counter: 0
    }
  },

  beforeCreate() {
    console.log('I am the first hook to get called!');
    console.log(`You can see that my data property is ${typeof this.counter}`); // undefined
  }
}
</script>

Created  — This hook is called after the instance is created. At this stage, the instance has finished processing, data observation (reactivity), computed properties, methods, watchers and event callbacks have been set up. You can’t interact with the DOM at this stage because your component has not been mounted. The $el property is not also available yet.

<script>
export default {
  data() {
    return {
      counter: 0
    }
  },

  created() {
    console.log('I am the created hook.');
    console.log(`You can now see that my data property is ${typeof this.counter}`);
  }
}
</script>

beforeMount  — At this stage, the template is compiled, either from the template or render options, or from the outerHTML of the element that Vue was initialized to. The template isn’t rendered yet and the $el method doesn’t exist either. Please note that this hook is not called during sever-side rendering.

<script>
export default {
  beforeMount() {
    console.log(`I am ready to be rendered.!`)
  }
}
</script>

Mounted  — Called after the instance has been mounted, where el property is replaced by the newly created vm.$el. If the root instance is mounted to an in-document element, vm.$el will also be in-document when mounted is called. The component becomes fully functional after the mounted hook is called and we can fully interact with it.

One thing to take note of is that the mounted hook doesn’t guarantee that the element has been added to DOM. To execute a code that is DOM dependent at this stage, put the code inside a callback method to the Vue.nextTick() function (Vue.nextTick() defers its callback to be executed after the next DOM update cycle). See the example below:

<template>
  <p>I'm text inside the component.</p>
</template>

<script>
export default {
  mounted() {
    // Element might not have been added to the DOM yet
    this.$nextTick(() => {
        // Element has been definitely added to the DOM
       console.log(this.$el.textContent); // I'm text inside the component.
    }
  }
}
</script>

beforeUpdate  — It is called anytime changes are made to our data and the DOM needs to be updated, right before the DOM is patched. This is a good place to access the existing DOM before an update, e.g. to manually remove an added event listeners. This hook is not called during server-side rendering, because only the initial render is performed at server-side.

<script>
export default {
  data() {
    return {
      counter: 0
    }
  },

  beforeUpdate() {
    console.log(this.counter) // Logs the counter value every second, before the DOM updates.
  },

  created() {
    setInterval(() => {
      this.counter++
    }, 1000)
  }
}
</script>

Updated  — hook is fired after a change has been made. The component’s DOM would have been updated when this hook is called, so you can perform DOM-dependent operations here. However, in most cases you should avoid changing state inside the hook. To react to state changes, it’s usually better to use a computed property or watcher instead.

Note that updated does not guarantee that all child components have also been re-rendered. If you want to wait until the entire view has been re-rendered, you can use vm.$nextTick inside of updated:

<template>
  <p ref="dom-element">{{counter}}</p>
</template>
<script>
export default {
  data() {
    return {
      counter: 0
    }
  },

  updated() {
    // Fired every second, should always be true
    console.log(+this.$refs['dom-element'].textContent === this.counter)
  },

  created() {
    setInterval(() => {
      this.counter++
    }, 1000)
  }
}
</script>

beforeDestroy  — Called right before a Vue instance is destroyed. At this stage the instance is still fully functional. You can perform necessary cleanups here. Please note that this hook is not called during sever-side rendering.

<script>
export default {
  data() {
    return {
      counter: 0
    }
  },

  beforeDestroy() {
    // Clean up the counter.
    // (In this case, effectively nothing)
    this.counter = null
    delete this.counter
  }
}
</script>

Destroyed  — Called after a Vue instance has been destroyed. When this hook is called, all directives of the Vue instance have been unbound, all event listeners have been removed, and all child Vue instances have also been destroyed. Please note that this hook is not called during sever-side rendering.

<script>
import DestroyerNotifierService from './notifier'

export default {
  destroyed() {
    console.log(this) // There's practically nothing here!
    DestroyerNotifierService.informThem('Component destroyed')
  }
}
</script>

All lifecycle hooks automatically have their this context bound to the component instance, so that you can access data, computed properties, and methods. This means you should not use an arrow function to define a lifecycle method (e.g. created: () => this.fetchTodos()). The reason is arrow functions bind the parent context, so this will not be the Vue instance as you expect and this.fetchTodos will be undefined.

In order words, arrow functions does not have their own value of this. The value of this in an arrow function is inherited from the enclosing (lexical) scope. So, you cannot use them inside a hook.

Conclusion

In this article, we have learnt about Vuejs Component lifecycle and their applications.

Thanks for reading.

Top comments (3)

Collapse
 
maitandat1507 profile image
Mai Tấn Đạt

Please note that this hook is not called during sever-side rendering.
and another sentence in the article
only the initial render is performed at server-side

May I ask you when the "initial render" phase you mentioned above? Isn't it created phase?

Collapse
 
sidratariq profile image
sidratariq

In mounted() event example round close bracket is missing

Collapse
 
maitandat1507 profile image
Mai Tấn Đạt

Very good article with detail definition of all phrase of Lifecycle.
Many thank for your work!