Vue.js 3 Template Refs Tutorial

In this Vue tutorial we learn how to access DOM nodes directly from within Vue and use lifecycle methods to manipulate it.

We cover how to define and access refs on both elements and entire component instances.

Lesson Project

If you want to follow along with the examples, you will need an app generated by the Vue CLI as well as the following extra component.

  • src/components/TemplateRef.vue

The project should look similar to the following.

Example: project
project-folder/
├── src/
|   ├── components/
|   |   └── TemplateRef.vue
|   └── App.vue

The root App component imports and uses the TemplateRef component.

Example: src/App.vue
<template>
  <template-ref />
</template>

<script>
import TemplateRef from './components/TemplateRef'

export default {
  components: { TemplateRef }
}
</script>

The TemplateRef component can just show an identifying message in a paragraph to start with.

Example: src/components/TemplateRef.vue
<template>
  <p>Template Ref Component</p>
</template>

What are Template Refs?

Template Refs make it possible to access DOM nodes directly from within Vue.

As an example, let’s say we have a login form and want to focus the email/username field when the page loads. We can access the input with a template ref and focus it in a lifecycle method .

How to define a template ref

We define a template ref with the ref attribute, which will register a new reference to an element or component. It’s value is an identifier that we use later on to access the reference.

Syntax: ref
<element ref="identifier" />
// or
<component ref="identifier" />

As an example, let’s create a text field in our TemplateRef component with a ref called textInputRef . We’ll also add a focus CSS style to help the demonstration.

Example: src/components/TemplateRef.vue
<template>
  <p>
    <input type="text" ref="textInputRef" />
  </p>
</template>

<style scoped>
:focus {
  outline-color:blue;
  outline-width:4px
}
</style>

How to access a template ref

To access a template ref, we use the $refs instance variable with the identifier we assigned to it.

Syntax: $refs
this.$refs.identifier

As an example, let’s access our textInputRef and chain the focus method to it in the mounted lifecycle hook. The method will set the text input to a focussed state when the component is mounted.

Example: src/components/TemplateRef.vue
<template>
  <p>
    <input type="text" ref="textInputRef" />
  </p>
</template>

<script>
export default {
  mounted() {
    this.$refs.textInputRef.focus()
  }
}
</script>


<style scoped>
:focus {
  outline-color:blue;
  outline-width:4px
}
</style>

If we save the file and reload the page in the browser, the text input will show a blue outline, indicating that it has focus.

Template refs on components

We mentioned earlier that ref can be used on a component as well.

Let’s see an example by creating a new component called GreetingMessage .

Example: project
project-folder/
├── src/
|   ├── components/
|   |   ├── TemplateRef.vue
|   |   └── GreetingMessage.vue
|   └── App.vue

It will have a single data property that we output in the template.

Example: src/components/GreetingMessage.vue
<template>
  <p>{{ msg }}</p>
</template>

<script>
export default {
  data() {
    return { msg: 'Hello, World!' }
  }
}
</script>

We’ll nest the new component in TemplateRef and add a ref to it. Then we’ll access the msg data property with the identifier and log it to the console.

Example: src/components/TemplateRef.vue
<template>
  <greeting-message ref="componentRef" />
</template>

<script>
import GreetingMessage from './GreetingMessage.vue'

export default {
  components: { GreetingMessage },
  mounted() {
    console.log(this.$refs.componentRef.msg)
  }
}
</script>

If we run the example in the browser, the console will show the “Hello, World!” message from the GreetingMessage component.