Reach Into the DOM With ref="..."
Template Refs
A ref attribute in the template exposes the underlying DOM element or component instance as a Vue ref you can read in script setup.
What you'll learn
- Use ref="name" plus a matching ref()
- Access the element in onMounted
- Type the ref with TypeScript
Sometimes you need direct access to a DOM element — to focus an input, measure size, or call an imperative API. Template refs are how Vue exposes those.
Basic DOM Ref
Declare a ref with the same name as the template’s ref attribute. After mount, the ref’s value is the DOM node.
<script setup lang="ts">
import { ref, onMounted } from 'vue'
const inputRef = ref<HTMLInputElement | null>(null)
onMounted(() => {
inputRef.value?.focus()
})
</script>
<template>
<input ref="inputRef" placeholder="Auto-focused" />
</template> The ref is null until the component mounts, hence the optional chaining.
Refs Inside v-for
When you put ref on an element inside v-for, Vue collects all the elements into an array (in mount order, which may not match render order).
<script setup lang="ts">
import { ref } from 'vue'
const itemRefs = ref<HTMLElement[]>([])
</script>
<template>
<li v-for="(item, i) in items" :key="item.id" :ref="el => itemRefs[i] = el as HTMLElement">
{{ item.name }}
</li>
</template> Component Refs
Putting ref on a component gives you the component’s public instance. To expose values to the parent, the child must call defineExpose.
<!-- Child.vue -->
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
function reset() { count.value = 0 }
defineExpose({ count, reset })
</script> <!-- Parent -->
<script setup lang="ts">
import { ref } from 'vue'
import Child from './Child.vue'
const childRef = ref<InstanceType<typeof Child> | null>(null)
function onClick() {
childRef.value?.reset()
}
</script>
<template>
<Child ref="childRef" />
<button @click="onClick">Reset child</button>
</template>