In order to create a reference to an HTML element we use the ref
attribute, where we set a reference name. We link the reference to a reactive state with the same name. For Vue 3.5+, we can use useTemplateRef()
which is more type-safe.
We can also use an inline expression or method for assigning the element instance to any reactive state.
const input = ref(null) onMounted(() => { input.value.focus() }) const inputRef = useTemplateRef('input-ref') onMounted(() => { inputRef .value.focus() }) watchEffect(() => { if (input.value) { input.value.focus() } else { // not mounted yet, or the element was unmounted (e.g. by v-if) } }) const myRef = ref(null) const setMyRef = (el) => { myRef = el }
<template> <input ref="input" /> <input ref="input-ref" /> <input :ref="(el) => { myref = el }" /> <input :ref="setMyRef" /> </template>
To reference a component, we use the same approach applied to HTML elements. Once having the reference we have access to the instance of the component.
import Child from './Child.vue' const child = ref(null) onMounted(() => { // child.value will hold an instance of <Child /> }) const childRef = useTemplateRef('child') onMounted(() => { // childRef.value will hold an instance of <Child /> })
<template> <Child ref="child" /> </template>
In <script setup>
all component content is private by default, so, if you want to access to any child’s state or function, they need to be exposed.
<script setup> import { ref } from 'vue' const a = 1 const b = ref(2) // Compiler macros, such as defineExpose, don't need to be imported defineExpose({ a, b }) </script>
We can reference multiple elements at once. For this case we need to set the ref
attribute to the element which will render the list of elements.
const list = ref([ /* ... */ ]) const items = ref([]) onMounted(() => console.log(items.value)) const itemRefs = useTemplateRef('items') onMounted(() => console.log(itemRefs.value))
<template> <ul> <li v-for="item in list" ref="items"> {{ item }} </li> </ul> </template>
References