Template Refs

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.

4 min read Level 2/5 #vue#refs#dom
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>
Async Components →