Tutorials Logic, IN info@tutorialslogic.com

Vue Template Refs useTemplateRef DOM Access

DOM Escape Hatch

A template ref gives code access to a rendered element or child component instance. Use it for imperative browser APIs such as focus, measurement, or third-party widgets when declarative props and state cannot express the action. Refs are unavailable before mount and can become null when conditional rendering removes the target.

What are Template Refs?

Template refs give you direct access to a DOM element or child component instance. Use them when you need to do something that Vue's declarative model can't handle - like focusing an input, measuring element dimensions, or calling a method on a child component.

Template Refs - DOM Access, Component Refs, defineExpose

Template Refs - DOM Access, Component Refs, defineExpose
<template>
  <div>
    <!-- ref attribute - matches the ref name in script -->
    <input ref="inputEl" placeholder="I'll be focused on mount" />
    <button @click="focusInput">Focus Input</button>

    <!-- Canvas ref -->
    <canvas ref="canvasEl" width="300" height="150"></canvas>

    <!-- Measure element -->
    <div ref="boxEl" class="box">Measure me</div>
    <p>Box size: {{ boxSize.width }}x{{ boxSize.height }}</p>

    <!-- v-for refs - array of elements -->
    <ul>
      <li v-for="item in items" :key="item.id" :ref="el => setItemRef(el, item.id)">
        {{ item.name }}
      </li>
    </ul>
    <button @click="scrollToItem(2)">Scroll to item 2</button>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, useTemplateRef } from 'vue'

// Modern API (Vue 3.5+)
const inputEl  = useTemplateRef('inputEl')
const canvasEl = useTemplateRef('canvasEl')
const boxEl    = useTemplateRef('boxEl')

// Or classic ref (same name as ref attribute)
// const inputEl = ref(null)

const items = ref([
  { id: 1, name: 'Item One' },
  { id: 2, name: 'Item Two' },
  { id: 3, name: 'Item Three' },
])

const boxSize = reactive({ width: 0, height: 0 })
const itemRefs = new Map()

onMounted(() => {
  // Access DOM element after mount
  inputEl.value?.focus()

  // Draw on canvas
  const ctx = canvasEl.value?.getContext('2d')
  if (ctx) {
    ctx.fillStyle = '#42b883'
    ctx.fillRect(10, 10, 280, 130)
    ctx.fillStyle = 'white'
    ctx.font = '24px Arial'
    ctx.fillText('Vue Canvas!', 80, 80)
  }

  // Measure element
  if (boxEl.value) {
    const rect = boxEl.value.getBoundingClientRect()
    boxSize.width  = Math.round(rect.width)
    boxSize.height = Math.round(rect.height)
  }
})

function focusInput() {
  inputEl.value?.focus()
  inputEl.value?.select()
}

function setItemRef(el, id) {
  if (el) itemRefs.set(id, el)
  else itemRefs.delete(id)
}

function scrollToItem(id) {
  itemRefs.get(id)?.scrollIntoView({ behavior: 'smooth' })
}
</script>

What are Template Refs? - HTML Example

What are Template Refs? - HTML Example
<!-- ChildComponent.vue -->
<template>
  <div>
    <input ref="inputEl" v-model="value" />
    <p>Internal count: {{ count }}</p>
  </div>
</template>

<script setup>
import { ref, useTemplateRef } from 'vue'

const value = ref('')
const count = ref(0)
const inputEl = useTemplateRef('inputEl')

// defineExpose - explicitly expose what parent can access
// Without defineExpose, <script setup> components are closed by default
defineExpose({
  // Expose methods
  focus() {
    inputEl.value?.focus()
  },
  clear() {
    value.value = ''
  },
  increment() {
    count.value++
  },
  // Expose data (read-only)
  getValue: () => value.value,
  // Expose ref directly
  count,
})
</script>

What are Template Refs? - HTML Example 2

What are Template Refs? - HTML Example 2
<!-- Parent.vue - accessing child component methods -->
<template>
  <div>
    <ChildComponent ref="childRef" />
    <button @click="childRef?.focus()">Focus Child Input</button>
    <button @click="childRef?.clear()">Clear Child Input</button>
    <button @click="childRef?.increment()">Increment Child Count</button>
    <p>Child value: {{ childRef?.getValue() }}</p>
    <p>Child count: {{ childRef?.count }}</p>
  </div>
</template>

<script setup>
import { useTemplateRef, onMounted } from 'vue'
import ChildComponent from './ChildComponent.vue'

const childRef = useTemplateRef('childRef')

onMounted(() => {
  // Access exposed methods after mount
  childRef.value?.focus()
})
</script>

Ref Timing

Declare a matching ref in script and use it only after onMounted or nextTick when DOM updates must finish first. A ref inside v-for represents multiple elements and should not become the primary data model; identify records in reactive state and use DOM refs only for the final imperative operation.

A component ref exposes internal implementation unless the child deliberately limits its public surface with defineExpose. Prefer props and events for normal communication. Clean up observers, widgets, and listeners associated with a ref when the element changes or the owner unmounts.

Before you move on

Vue Template Refs useTemplateRef DOM Access Mastery Check

2 checks
  • Template refs give you direct access to a DOM element or child component instance.
  • Use them when you need to do something that Vue's declarative model can't handle - like focusing an input, measuring element dimensions, or calling a method on a child component.

Template Ref Boundary

  • Reading before mount

    A template ref is null until its element or child is mounted and can return to null when conditionally removed. Read it after mount and guard every conditional access.
Browse Free Tutorials

Explore 500+ free tutorials across 20+ languages and frameworks.