Frontend Development

Vue 3 DOM Manipulation with useTemplateRef

Vue 3 DOM Manipulation with useTemplateRef

Normally, Vue encourages us to work with reactivity instead of touching the DOM directly. But sometimes you need low-level DOM access (e.g., focusing an input, measuring element size, scrolling to a section).

 

 

In the Vue 3.3+ Composition API, we now have a clean utility: useTemplateRef.

What is useTemplateRef?

  • It’s a Composition API helper to easily grab template refs.

  • Think of it as a typed, reactive replacement for the old ref="myElement" + onMounted() combo.

  • It works by binding a template element to a JavaScript variable.

 

Basic Example: Focusing an Input

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

const inputEl = useTemplateRef('inputEl')

onMounted(() => {
  // Direct DOM manipulation
  inputEl.value?.focus()
})
</script>

<template>
  <input type="text" ref="inputEl" placeholder="I’ll be focused on mount" />
</template>

👉 inputEl.value will hold the actual DOM node.

 

Accessing Other DOM Properties

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

const box = useTemplateRef('box')

onMounted(() => {
  console.log('Box width:', box.value.offsetWidth)
  console.log('Box height:', box.value.offsetHeight)
})
</script>

<template>
  <div ref="box" style="width: 200px; height: 100px; background: lightblue;">
    Measured box
  </div>
</template>

Manipulating Scroll

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

const container = useTemplateRef('container')

function scrollToBottom() {
  container.value.scrollTop = container.value.scrollHeight
}
</script>

<template>
  <div ref="container" style="height: 150px; overflow-y: auto; border: 1px solid #ccc;">
    <p v-for="n in 20" :key="n">Item {{ n }}</p>
  </div>
  <button @click="scrollToBottom">Scroll to bottom</button>
</template>

 

Comparing useTemplateRef vs Classic ref

Old way (before Vue 3.3):

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

const inputEl = ref(null)

onMounted(() => {
  inputEl.value.focus()
})
</script>

<template>
  <input ref="inputEl" />
</template>

New way with useTemplateRef:

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

const inputEl = useTemplateRef('inputEl')

onMounted(() => {
  inputEl.value.focus()
})
</script>

<template>
  <input ref="inputEl" />
</template>

 

Best Practices ⚡

  • Use reactivity (v-model, computed, etc.) first.

  • Only use useTemplateRef when you need direct DOM access.

  • Always check el.value is not null before using it.

  • Prefer wrapping DOM logic in composables (reusable hooks).

 
 

0 0 votes
Article Rating

What's your reaction?

Excited
0
Happy
0
Not Sure
0
Confused
0

You may also like

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments