Every Vue component follows a predictable sequence of initialization, rendering, patching, and teardown. During each phace Vue exposes dedicated hooks so you can run custom logic at the exact moment you need.
Declaring Hooks
Hooks are plain instance methods. The framework envokes them automatically; you only need to provide the body.
import { defineComponent } from 'vue'
export default defineComponent({
mounted() {
console.log('DOM is ready')
}
})
Inside every hook the runtime binds this to the current component instance. Do not use arrow functions, because they preserve the outer lexical scope and you will lose access to the component.
Lifecycle Overview
| Hook | Fires when… |
|---|---|
beforeCreate |
Instance is initialized but reactivity and events are not yet set up. |
created |
Props, data, computed, watchers, and methods are ready; template is not yet compiled. |
beforeMount |
Template is compiled and the virtual DOM is about to be rendered for the first time. |
mounted |
Real DOM has been created and inserted; $el is now available. |
beforeUpdate |
Reactive data changed; virtual DOM is about to be patched. |
updated |
DOM has been updated to reflect the new state. |
beforeUnmount |
Component is still fully functional but is about to be removed. |
unmounted |
Component is gone—its DOM nodes, reactive effects, and child components have been cleaned up. |
Hook Details
beforeCreate
Useful for global configuration that must run before any reactivity is installed.
beforeCreate() {
console.log('No data, no watchers yet')
}
created
Perfect for fetching initial data or setting up non-reactive state.
async created() {
this.posts = await api.fetchPosts()
}
beforeMount
Rarely needed; sometimes used to tweak the render function just before the first paint.
beforeMount() {
console.log('About to render for the first time')
}
mounted
Ideal for third-party libraries that require real DOM nodes, such as charts or map widgets.
mounted() {
this.chart = new Chart(this.$refs.canvas, this.chartConfig)
}
beforeUpdate
Access the pre-patch DOM state; useful for manual diffing or measuring layout.
beforeUpdate() {
this.scrollTop = this.$refs.list.scrollTop
}
updated
React to DOM changes; avoid mutating reactive data here to prevent infinite loops.
updated() {
this.$nextTick(() => this.$refs.input.focus())
}
beforeUnmount
Clean up timers, cancel network requests, or remove global event listeners.
beforeUnmount() {
clearInterval(this.timerId)
}
unmounted
Perform final teardown; the component instance is no longer usable.
unmounted() {
console.log('Component is gone')
}
Complete Example
<template>
<div>
<p>{{ counter }}</p>
<button @click="counter++">+</button>
</div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
name: 'LifecycleLogger',
data() {
return { counter: 0 }
},
beforeCreate() { console.log('beforeCreate') },
created() { console.log('created') },
beforeMount() { console.log('beforeMount') },
mounted() { console.log('mounted') },
beforeUpdate() { console.log('beforeUpdate') },
updated() { console.log('updated') },
beforeUnmount() { console.log('beforeUnmount') },
unmounted() { console.log('unmounted') }
})
</script>
Mounting and then incrementing the counter will print the hooks in the exact order listed above.