Lesson 11 / 25
Lifecycle Hooks
Running code at the right moment.
Mount, update, unmount
Each component instance goes through creation, mounting into the DOM, updates when reactive state changes, and unmounting. In the Composition API you register callbacks with onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount and onUnmounted. Code in <script setup> itself runs during setup, before the DOM exists, so DOM access belongs in onMounted. Use onUnmounted (or onBeforeUnmount) to clean up timers, listeners and subscriptions. The Options API equivalents are mounted, updated, unmounted and so on. Hooks must be registered synchronously during setup, not inside a later callback.
A clock with a template ref and cleanup
Focus an input on mount and stop a timer on unmount.
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const now = ref(new Date())
const input = ref(null) // filled by ref="input" after mount
let timer
onMounted(() => {
input.value.focus()
timer = setInterval(() => { now.value = new Date() }, 1000)
})
onUnmounted(() => {
clearInterval(timer)
})
</script>
<template>
<input ref="input" placeholder="Focused on mount" />
<p>{{ now.toLocaleTimeString() }}</p>
</template>Clean up everything you start
Every setInterval, addEventListener or socket subscription created in onMounted needs a matching cleanup, or it keeps running after the component is gone.
Quick check: Where should code that reads the rendered DOM run?
- In defineProps
- At the top level of script setup
- Inside a computed getter
- Inside onMounted
Answer
Inside onMounted — The DOM exists only after mounting.