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