Chapter 94: Vue Lifecycle Hooks
Vue Lifecycle Hooks
These are special named functions (or callbacks) that Vue automatically calls at very precise moments during the life of a component instance — from creation → mounting → updating → destruction.
They are your chance to run code exactly when something important happens to the component.
Understanding lifecycle hooks is what separates people who write working Vue code from people who write robust, performant, bug-free Vue code.
1. The Full Lifecycle – Visual Timeline (Memorize This Sequence)
Here’s the complete order (Vue 3 – 2026 standard):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 |
beforeCreate() ── instance is created, but data/props not ready yet created() ── data & computed are ready, but NO DOM yet beforeMount() ── template compiled, about to insert into DOM mounted() ── DOM is rendered & inserted – first time you can safely access $el / refs beforeUpdate() ── data changed, about to re-render (pre-patch) updated() ── DOM has been patched & updated beforeUnmount() ── component is about to be destroyed (cleanup time) unmounted() ── component is gone from DOM, instance is dead |
Modern Composition API names (what you use in <script setup>):
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
onBeforeMount() onMounted() onBeforeUpdate() onUpdated() onBeforeUnmount() onUnmounted() // Less common onBeforeCreate() // almost never needed onServerPrefetch() // SSR only onRenderTriggered() onRenderTracked() |
2. Real, Practical Example – Full Component Showing Every Hook
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<template> <div class="lifecycle-demo"> <h2>Lifecycle Hooks Demo</h2> <p>Count: {{ count }}</p> <button @click="count++">+1</button> <button @click="showChild = !showChild"> {{ showChild ? 'Hide' : 'Show' }} Child Component </button> <ChildComponent v-if="showChild" :propValue="count" /> </div> </template> <script setup lang="ts"> import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue' const count = ref(0) const showChild = ref(true) console.log('Script setup top level – runs once when component is defined') // ── Lifecycle Hooks ───────────────────────────────────────────── onBeforeMount(() => { console.log('onBeforeMount – template compiled, about to insert into DOM') }) onMounted(() => { console.log('onMounted – DOM is ready! You can safely access refs / $el') // Perfect place to: fetch data, add event listeners, focus inputs, init 3rd-party libs }) onBeforeUpdate(() => { console.log('onBeforeUpdate – data changed, Vue is about to re-render') // Rarely used – good for debugging or measuring before patch }) onUpdated(() => { console.log('onUpdated – DOM has been patched after update') // Rarely used – good for DOM measurement after update }) onBeforeUnmount(() => { console.log('onBeforeUnmount – component is about to be destroyed') // Perfect place to: remove event listeners, clear timers, cancel API requests }) onUnmounted(() => { console.log('onUnmounted – component is gone from DOM, instance is dead') // Cleanup is done – no more this component }) </script> <style scoped> .lifecycle-demo { padding: 2rem; max-width: 600px; margin: 2rem auto; background: white; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.08); } </style> |
ChildComponent.vue (to see mount/unmount)
|
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<template> <div class="child"> <h3>Child Component</h3> <p>Prop value: {{ propValue }}</p> </div> </template> <script setup lang="ts"> import { onMounted, onBeforeUnmount, onUnmounted } from 'vue' defineProps<{ propValue: number }>() onMounted(() => console.log('Child: onMounted')) onBeforeUnmount(() => console.log('Child: onBeforeUnmount')) onUnmounted(() => console.log('Child: onUnmounted')) </script> |
What you see in console when you interact:
- Page loads → onBeforeMount → onMounted
- Click “+1” multiple times → onBeforeUpdate → onUpdated each time
- Click “Hide Child” → onBeforeUnmount (child) → onUnmounted (child)
- Click “Show Child” again → child onMounted again
- Click “Hide” again → child onBeforeUnmount & onUnmounted
3. The Most Important Hooks – When to Use Each (2026 Rules)
| Hook | When it runs | Best for (real-world) | Never do this here |
|---|---|---|---|
| onBeforeMount | After setup, before first DOM insert | Very rarely – almost never needed | Access refs / DOM |
| onMounted | After first render, DOM is ready | Fetch initial data, add event listeners, focus inputs, init 3rd-party libs (Chart.js, Mapbox, Swiper…) | — |
| onBeforeUpdate | Data changed, before re-render/patch | Debugging, measuring before DOM update (rare) | Mutate data |
| onUpdated | After re-render/patch | Measure DOM after update (e.g. height change) | Mutate data (loop risk) |
| onBeforeUnmount | Before removal from DOM | Cleanup: removeEventListener, clearInterval, cancel fetch/abort, remove resize observer | — |
| onUnmounted | After removal, instance is dead | Final cleanup (rare – most done in beforeUnmount) | Access refs / DOM |
4. Quick Summary Table – Lifecycle Hooks in 2026
| Hook | Options API name | Composition API name | Runs multiple times? | DOM ready? | Typical real use-case |
|---|---|---|---|---|---|
| beforeCreate | beforeCreate | (almost never used) | No | No | Very rare |
| created | created | (almost never used) | No | No | Very rare |
| beforeMount | beforeMount | onBeforeMount | No | No | Rare |
| mounted | mounted | onMounted | No | Yes | Fetch data, init libs |
| beforeUpdate | beforeUpdate | onBeforeUpdate | Yes | Yes | Debugging |
| updated | updated | onUpdated | Yes | Yes | DOM measurement after update |
| beforeUnmount | beforeUnmount | onBeforeUnmount | No | Yes | Cleanup (timers, listeners) |
| unmounted | unmounted | onUnmounted | No | No | Final cleanup (rare) |
Pro Tips from Real Projects (Hyderabad 2026)
- Most used hooks: onMounted (init), onBeforeUnmount (cleanup), onUpdated (rare DOM measurement)
- Never mutate state in onUpdated — causes infinite loop
- Always cleanup in onBeforeUnmount — timers, event listeners, AbortController, ResizeObserver, etc.
- Use onMounted for DOM access / refs / 3rd-party libs — not in setup()
- In server-side rendering (SSR / Nuxt) → onMounted runs only client-side
- Combine onMounted + nextTick() when you need DOM right after first render
Your mini homework:
- Create the component above
- Toggle the child → watch console logs for mount/unmount
- Add onBeforeUnmount to remove a fake timer
- Add onUpdated to log DOM height after count changes
Any part confusing? Want full examples for:
- Full lifecycle log + cleanup timer example?
- onMounted + third-party lib (Chart.js / Mapbox)?
- onBeforeUnmount + event listener / ResizeObserver cleanup?
- Lifecycle in <Transition> / <KeepAlive>?
Just tell me — we’ll trace the lifecycle of the next component together 🚀
