Vue Template Refs
Direct access to DOM elements and components
🎯 What are Template Refs?
Template refs provide direct access to DOM elements or child component instances in your template. Use them when you need to manipulate elements directly, focus inputs, or access component methods imperatively.
<!-- Basic Template Ref -->
<template>
<input ref="inputRef" type="text" />
<button @click="focusInput">Focus Input</button>
</template>
<script setup>
import { ref } from 'vue'
const inputRef = ref(null)
function focusInput() {
inputRef.value.focus()
}
</script>
Key Template Ref Concepts
Element Refs
Access DOM elements directly
<div ref="divRef"></div>
const divRef = ref(null)
Component Refs
Access child component instances
<ChildComp ref="childRef" />
const childRef = ref(null)
v-for Refs
Array of refs in loops
<div v-for="item in list"
ref="itemRefs">
</div>
Function Refs
Dynamic ref assignment
<div :ref="el => setRef(el)">
</div>
🔹 Basic Element Ref
Access and manipulate DOM elements directly:
<template>
<div>
<input ref="nameInput" type="text" placeholder="Enter name" />
<button @click="focusInput">Focus</button>
<button @click="clearInput">Clear</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const nameInput = ref(null)
function focusInput() {
nameInput.value.focus()
}
function clearInput() {
nameInput.value.value = ''
}
</script>
🔹 Component Ref
Access child component methods and properties:
<!-- Parent Component -->
<template>
<ChildComponent ref="childRef" />
<button @click="callChildMethod">Call Child Method</button>
</template>
<script setup>
import { ref } from 'vue'
import ChildComponent from './ChildComponent.vue'
const childRef = ref(null)
function callChildMethod() {
childRef.value.childMethod()
}
</script>
<!-- Child Component -->
<script setup>
import { defineExpose } from 'vue'
function childMethod() {
console.log('Child method called!')
}
// Expose method to parent
defineExpose({
childMethod
})
</script>
🔹 Refs in v-for Loops
Collect multiple element references in an array:
<template>
<div>
<div
v-for="(item, index) in items"
:key="item.id"
ref="itemRefs"
class="item"
>
{{ item.name }}
</div>
<button @click="highlightFirst">Highlight First</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const items = ref([
{ id: 1, name: 'Item 1' },
{ id: 2, name: 'Item 2' },
{ id: 3, name: 'Item 3' }
])
const itemRefs = ref([])
function highlightFirst() {
if (itemRefs.value[0]) {
itemRefs.value[0].style.background = 'yellow'
}
}
</script>
🔹 Function Refs
Use a function for dynamic ref assignment:
<template>
<div>
<input
v-for="n in 3"
:key="n"
:ref="el => setInputRef(el, n)"
type="text"
/>
<button @click="focusSecond">Focus Second Input</button>
</div>
</template>
<script setup>
import { ref } from 'vue'
const inputRefs = ref({})
function setInputRef(el, index) {
if (el) {
inputRefs.value[index] = el
}
}
function focusSecond() {
inputRefs.value[2]?.focus()
}
</script>
🔹 Practical Example - Video Player
Control a video element using template refs:
<template>
<div>
<video ref="videoRef" width="400">
<source src="video.mp4" type="video/mp4">
</video>
<div class="controls">
<button @click="play">Play</button>
<button @click="pause">Pause</button>
<button @click="restart">Restart</button>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const videoRef = ref(null)
function play() {
videoRef.value.play()
}
function pause() {
videoRef.value.pause()
}
function restart() {
videoRef.value.currentTime = 0
videoRef.value.play()
}
</script>