Template Refs
Get a direct reference to a DOM element or a child component instance using template refs.
Why You Sometimes Need Direct DOM Access
Vue's declarative model handles the vast majority of UI needs without touching the DOM directly. But some things — focusing an input, reading an element's measured size, integrating a non-Vue library — genuinely require a direct reference to the actual DOM node.
Creating a Template Ref
Add a ref attribute to an element in the template, and declare a matching ref() in <script setup> with the exact same name — Vue automatically connects the two after the component mounts.
<script setup>import { ref, onMounted } from 'vue';
const inputEl = ref(null); // must match the template\'s ref="inputEl"
onMounted(() => { inputEl.value.focus(); // inputEl.value is the actual <input> DOM element});</script>
<template> <input ref="inputEl" /></template>A template ref is null until the component has mounted — always access it inside onMounted or a later lifecycle hook/event handler, never during the component's initial setup.
Refs on Components
Placing a ref on a custom component gives you its exposed instance — but only whatever that child explicitly exposed with defineExpose, covered in the <script setup> lesson.
<script setup>import { ref } from 'vue';import CustomInput from './CustomInput.vue';
const customInputRef = ref(null);
function focusChild() { customInputRef.value.focus(); // works only if CustomInput exposed \'focus\'}</script>
<template> <CustomInput ref="customInputRef" /></template>Refs Inside v-for
A ref attribute inside a v-for loop collects into an array rather than a single element, in the same order as the source array.
<script setup>import { ref } from 'vue';
const itemRefs = ref([]);const items = ['A', 'B', 'C'];</script>
<template> <li v-for="item in items" :key="item" ref="itemRefs">{{ item }}</li></template>Common Beginner Mistakes
This bypasses Vue's reactivity model — reserve template refs for genuine DOM-level needs (focus, measurement, third-party library integration), not everyday data flow.
The names must match exactly for Vue to connect them — a mismatch silently leaves the ref's value as null.
FAQs
Yes — bind it with :ref="dynamicName" instead of a static string, useful for programmatically generated lists of refs.
They share the ref() function and .value access pattern, but a template ref specifically holds a DOM element or component instance rather than arbitrary reactive data.
Summary
Template refs are your escape hatch for genuine, direct DOM access, connected automatically once a component mounts. Next, you'll learn to build your own reusable DOM behavior with custom directives.