Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/use-template-ref-vue35.md
1---2title: Use useTemplateRef for Template Refs in Vue 3.5+3impact: MEDIUM4impactDescription: Legacy ref pattern is error-prone due to name matching requirement5type: best-practice6tags: [vue3, vue35, template-refs, useTemplateRef, composition-api]7---89# Use useTemplateRef for Template Refs in Vue 3.5+1011**Impact: MEDIUM** - Before Vue 3.5, template refs required declaring a `ref()` with a name exactly matching the template's ref attribute. This fragile connection breaks silently during refactoring. Vue 3.5's `useTemplateRef()` eliminates this issue with explicit binding and better TypeScript support.1213The legacy pattern causes no errors or warnings when names don't match - the ref simply stays null, leading to confusing debugging sessions.1415## Task Checklist1617- [ ] Use `useTemplateRef('ref-name')` in Vue 3.5+ projects18- [ ] The first argument must exactly match the ref attribute value in the template19- [ ] IDE support provides auto-completion for available ref names20- [ ] TypeScript automatically infers the element type2122**Incorrect (Legacy Pattern):**23```vue24<script setup>25import { ref, onMounted } from 'vue'2627// FRAGILE: Variable name MUST match template ref value exactly28const input = ref(null)2930// DANGER: After refactoring, names may not match31const inputElement = ref(null) // Renamed variable...3233onMounted(() => {34// NO ERROR - just silently null!35inputElement.value?.focus() // Does nothing36})37</script>3839<template>40<!-- But template still uses old name -->41<input ref="input" />42</template>43```4445```vue46<script setup>47import { ref } from 'vue'4849// TYPO: 'inupt' instead of 'input' - no warning!50const inupt = ref(null)51</script>5253<template>54<input ref="input" />55<!-- inupt.value will always be null -->56</template>57```5859**Correct (Vue 3.5+):**60```vue61<script setup>62import { useTemplateRef, onMounted } from 'vue'6364// CORRECT: Explicit binding - argument matches template ref65const inputElement = useTemplateRef('my-input')6667onMounted(() => {68inputElement.value?.focus()69})70</script>7172<template>73<!-- ref name is explicitly connected via useTemplateRef argument -->74<input ref="my-input" />75</template>76```7778```vue79<script setup>80import { useTemplateRef, onMounted } from 'vue'8182// BENEFITS:83// 1. Variable name is independent of ref attribute84// 2. IDE auto-completes available ref names85// 3. TypeScript infers correct element type86// 4. Typos in argument cause visible errors8788const searchInput = useTemplateRef('search-box')89const submitButton = useTemplateRef('submit-btn')9091onMounted(() => {92// TypeScript knows these are HTMLInputElement and HTMLButtonElement93searchInput.value?.focus()94submitButton.value?.disabled = false95})96</script>9798<template>99<input ref="search-box" type="search" />100<button ref="submit-btn">Submit</button>101</template>102```103104## Limitation: v-for Refs105106`useTemplateRef()` does **NOT** work with `v-for` refs. You must use the legacy `ref()` pattern for collecting multiple element references in a loop.107108```vue109<script setup>110import { ref, onMounted } from 'vue'111112// CORRECT: Legacy pattern required for v-for refs113const itemRefs = ref([])114115onMounted(() => {116// itemRefs.value is an array of DOM elements117itemRefs.value.forEach(el => {118console.log(el.textContent)119})120})121</script>122123<template>124<ul>125<li v-for="item in items" ref="itemRefs" :key="item.id">126{{ item.text }}127</li>128</ul>129</template>130```131132**Why this limitation exists:** When using `v-for`, Vue populates the ref with an array of elements. The `useTemplateRef()` API was designed for single element references and does not support the array population mechanism that `v-for` requires.133134## Migration Guide135136```vue137<!-- BEFORE (Vue < 3.5) -->138<script setup>139import { ref } from 'vue'140const myElement = ref(null) // Name must match template141</script>142<template>143<div ref="myElement"></div>144</template>145146<!-- AFTER (Vue 3.5+) -->147<script setup>148import { useTemplateRef } from 'vue'149const element = useTemplateRef('my-element') // Any variable name150</script>151<template>152<div ref="my-element"></div>153</template>154```155156## Reference157- [Vue.js Template Refs - Composition API](https://vuejs.org/guide/essentials/template-refs.html#accessing-the-refs)158- [Vue 3.5 Release Notes](https://blog.vuejs.org/posts/vue-3-5)159