Vue Lifecycle Hooks
Execute code at specific stages of component lifecycle
๐ What are Lifecycle Hooks?
Lifecycle hooks are special methods that run at specific stages of a component's life. They let you execute code when a component is created, mounted, updated, or destroyed, giving you control over component behavior throughout its existence.
onMounted(() => {
console.log('Component is now mounted!')
})
Main Lifecycle Hooks
onMounted
After component is added to DOM
onMounted(() => {
// DOM is ready
})
onUpdated
After reactive data changes
onUpdated(() => {
// DOM updated
})
onUnmounted
Before component is removed
onUnmounted(() => {
// Cleanup
})
onBeforeMount
Before mounting to DOM
onBeforeMount(() => {
// Before DOM
})
๐น Lifecycle Stages
Components go through these stages in order:
- Creation: Component instance is initialized
- Mounting: Component is inserted into DOM
- Updating: Component re-renders when data changes
- Unmounting: Component is removed from DOM
๐น onMounted Hook
Run code after component is added to the DOM:
<template>
<div ref="container">
<h2>{{ message }}</h2>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const message = ref('Hello')
const container = ref(null)
onMounted(() => {
console.log('Component mounted!')
console.log('DOM element:', container.value)
// Safe to access DOM here
container.value.style.background = 'lightblue'
})
</script>
Common uses: Fetch data, set up timers, access DOM elements, initialize third-party libraries.
๐น onUpdated Hook
Run code after component updates due to data changes:
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="count++">Increment</button>
</div>
</template>
<script setup>
import { ref, onUpdated } from 'vue'
const count = ref(0)
onUpdated(() => {
console.log('Component updated! New count:', count.value)
})
</script>
Console Output (after clicking):
Component updated! New count: 1 Component updated! New count: 2
๐น onUnmounted Hook
Clean up before component is destroyed:
<script setup>
import { onMounted, onUnmounted } from 'vue'
let timer = null
onMounted(() => {
// Start a timer
timer = setInterval(() => {
console.log('Tick')
}, 1000)
})
onUnmounted(() => {
// Clean up timer
if (timer) {
clearInterval(timer)
console.log('Timer cleaned up')
}
})
</script>
Common uses: Clear timers, remove event listeners, cancel API requests, disconnect websockets.
๐น onBeforeMount & onBeforeUpdate
Run code before mounting or updating:
import { onBeforeMount, onBeforeUpdate } from 'vue'
onBeforeMount(() => {
console.log('About to mount')
// DOM not available yet
})
onBeforeUpdate(() => {
console.log('About to update')
// Access old DOM state
})
๐น Complete Lifecycle Example
See all hooks in action:
<template>
<div>
<h2>{{ title }}</h2>
<button @click="title = 'Updated!'">Update</button>
</div>
</template>
<script setup>
import { ref, onBeforeMount, onMounted, onBeforeUpdate,
onUpdated, onBeforeUnmount, onUnmounted } from 'vue'
const title = ref('Original')
onBeforeMount(() => {
console.log('1. Before Mount')
})
onMounted(() => {
console.log('2. Mounted')
})
onBeforeUpdate(() => {
console.log('3. Before Update')
})
onUpdated(() => {
console.log('4. Updated')
})
onBeforeUnmount(() => {
console.log('5. Before Unmount')
})
onUnmounted(() => {
console.log('6. Unmounted')
})
</script>
Console Output:
1. Before Mount 2. Mounted (click button) 3. Before Update 4. Updated (component removed) 5. Before Unmount 6. Unmounted
๐น Options API Lifecycle
Lifecycle hooks in Options API (older syntax):
export default {
data() {
return { count: 0 }
},
beforeCreate() {
console.log('Before Create')
},
created() {
console.log('Created')
},
beforeMount() {
console.log('Before Mount')
},
mounted() {
console.log('Mounted')
},
beforeUpdate() {
console.log('Before Update')
},
updated() {
console.log('Updated')
},
beforeUnmount() {
console.log('Before Unmount')
},
unmounted() {
console.log('Unmounted')
}
}
๐น Practical Example: Data Fetching
Common pattern for loading data:
<template>
<div>
<p v-if="loading">Loading...</p>
<div v-else>
<h2>{{ data.title }}</h2>
<p>{{ data.body }}</p>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const loading = ref(true)
const data = ref({})
onMounted(async () => {
try {
const response = await fetch('https://api.example.com/data')
data.value = await response.json()
} catch (error) {
console.error('Failed to fetch:', error)
} finally {
loading.value = false
}
})
</script>