
Normally, Vue encourages us to work with reactivity instead of touching the DOM directly. But sometimes you need low-level DOM access (e.g., focusing an input, measuring element size, scrolling to a section).
In the Vue 3.3+ Composition API, we now have a clean utility: useTemplateRef
.
What is useTemplateRef
?
-
It’s a Composition API helper to easily grab template refs.
-
Think of it as a typed, reactive replacement for the old
ref="myElement"
+onMounted()
combo. -
It works by binding a template element to a JavaScript variable.
Basic Example: Focusing an Input
<script setup> import { useTemplateRef, onMounted } from 'vue' const inputEl = useTemplateRef('inputEl') onMounted(() => { // Direct DOM manipulation inputEl.value?.focus() }) </script> <template> <input type="text" ref="inputEl" placeholder="I’ll be focused on mount" /> </template>
👉 inputEl.value
will hold the actual DOM node.
Accessing Other DOM Properties
<script setup> import { useTemplateRef, onMounted } from 'vue' const box = useTemplateRef('box') onMounted(() => { console.log('Box width:', box.value.offsetWidth) console.log('Box height:', box.value.offsetHeight) }) </script> <template> <div ref="box" style="width: 200px; height: 100px; background: lightblue;"> Measured box </div> </template>
Manipulating Scroll
<script setup> import { useTemplateRef } from 'vue' const container = useTemplateRef('container') function scrollToBottom() { container.value.scrollTop = container.value.scrollHeight } </script> <template> <div ref="container" style="height: 150px; overflow-y: auto; border: 1px solid #ccc;"> <p v-for="n in 20" :key="n">Item {{ n }}</p> </div> <button @click="scrollToBottom">Scroll to bottom</button> </template>
Comparing useTemplateRef
vs Classic ref
Old way (before Vue 3.3):
<script setup> import { ref, onMounted } from 'vue' const inputEl = ref(null) onMounted(() => { inputEl.value.focus() }) </script> <template> <input ref="inputEl" /> </template>
New way with useTemplateRef
:
What's your reaction?
Excited
0
Happy
0
Not Sure
0
Confused
0