Integrating charts, maps, focus management and third-party widgets needs the DOM element and the right moment.
Each component goes through a lifecycle: setup runs, the component is mounted into the DOM, it updates when state changes, and finally it unmounts. Register callbacks with:
onMounted(fn)— the DOM exists; initialise third-party libraries, measure elements, add global listeners.onUpdated(fn)— after a re-render caused by state change (rarely needed).onUnmounted(fn)— clean up: remove listeners, clear timers, destroy library instances.onBeforeMount,onBeforeUpdate,onBeforeUnmountandonErrorCapturedexist for finer control.
These must be called synchronously during setup, not inside a setTimeout or after an await, because Vue binds them to the component currently being set up.
During SSR only setup runs; mounted hooks run on the client, so browser-only code belongs in onMounted.
To reach a DOM element, add a ref attribute in the template and read it with `useTemplateRef` (Vue 3.5+):
const input = useTemplateRef('search') // <input ref="search">
onMounted(() => input.value.focus())The ref is null until mount and after unmount. On a component tag, the ref gives the component instance, but with <script setup> only what the child exposes via defineExpose({ ... }) is accessible. Use refs sparingly: most things should be done declaratively through state.
Example
<script setup>
import { ref, useTemplateRef, onMounted, onUnmounted } from 'vue'
const box = useTemplateRef('box')
const width = ref(0)
let observer
onMounted(() => {
observer = new ResizeObserver(([entry]) => {
width.value = Math.round(entry.contentRect.width)
})
observer.observe(box.value) // box.value is the <div>
})
onUnmounted(() => observer.disconnect()) // always clean up
</script>
<template>
<div ref="box" class="panel">I am {{ width }}px wide</div>
</template>Remember
onMountedfor DOM work;onUnmountedto clean up- Register hooks synchronously in setup, never after an await
useTemplateRef('name')+ref="name"gives the element; null before mount
Watch out for
- Reading a template ref at the top of
<script setup>; the element doesn't exist until mounted.