Editor’s note: This post was updated on 4 October 2022 to include information on watching ref
s in Vue, as well as ensuring that all information reflects the most recent version of Vue.
In this tutorial, we’ll demonstrate how to reference HTML elements in your Vue.js components.
We’ll cover the following in detail:
- What is Vue.js?
- What are
ref
s in Vue.js? getElementById
in Vue.js- How to use
ref
s in Vue.js this.refs
in Vue.js- How Vue.js
ref
s work - Vue
$refs
- Getting DOM elements in Vue.js
- Watching
ref
s in Vue
This Vue ref
s tutorial is suited for all stages of developers who use Vue — including beginners. Here are a few prerequisites before you get started:
- Node.js version 10.x or above. Verify your version by running
node -v
in your terminal/command prompt - npm 6.7 or above
- A code editor; I highly recommend VS Code
- Vue.js 3 installed globally on your machine
- Vue CLI 3.0 installed on your machine. To do this, uninstall the old CLI version first with
npm uninstall -g vue-cli
, then install the new one usingnpm install -g @vue/cli
- Download a Vue starter project
- Unzip the downloaded project, navigate into it, and run
npm install
to keep all the dependencies up to date
What is Vue.js?
Vue.js is a progressive JavaScript framework created by Evan You and the Vue core team with contributions from more than 230 community members. Vue is used in more than 870,000 projects and has more than 175,000 stars on GitHub.
Vue.js is an approachable core library that focuses only on the view layer. It also has a massive ecosystem of supporting libraries that help you easily build responsive web experiences.
What are ref
s in Vue.js?
Ref
s are Vue.js instance properties that are used to register or indicate a reference to HTML elements or child elements in the template of your application.
If a ref
attribute is added to an HTML element in your Vue template, you’ll then be able to reference that element or even a child element in your Vue instance. You can also access the DOM element directly; it is a read-only attribute and returns an object.
getElementById
in Vue.js
The use of JavaScript’s getElementById
is not encouraged in Vue, as it creates performance issues. Vue’s ref
helps you “reference” DOM elements in a more efficient way.
How to use ref
s in Vue.js
The ref
attribute makes a DOM element selectable by serving as the key in the parent $ref
attribute.
Putting a ref
attribute in an input element, for instance, will expose the parent DOM node as this.$refs.input
, or you can say this.refs["input"]
.
For a quick visual guide on referencing with $refs
in Vue.js, check out this video tutorial.
this.refs
in Vue
You can manipulate a DOM element by defining methods on the element’s reference. For example, you could focus on an input element with this
:
this.$refs["input"].focus()
In this way, ref
s can be used just like the document.querySelector('.element')
in JavaScript or the $('.element')
in jQuery. While document.querySelector()
performs some of the functions of ref
s, ref
s are more efficient, because they give you direct access to the specific element you need. On the other hand, document.querySelector()
simply returns the first element in your DOM that matches the selector you specified. The $refs
can be accessed both inside the Vue.js instance and outside of it. However, they are not data properties, so they are not reactive.
On template inspection in your browser, $refs
do not show up at all because it is not an HTML attribute; it is only a Vue template attribute.
How Vue.js ref
s work
If you followed this post from the start, you should have downloaded the starter project and opened it up on VS Code. Open the components
folder and copy this into the test.vue
file:
<template> <div> <h2>Hello this is for refs man!</h2> <p>You have counted {{this.counter}} times</p> <input type="text" ref="input"> <button @click="submit">Add 1 to counter</button> </div> </template> <script> export default { name: 'Test', data(){ return { counter: 0 } }, methods: { submit(){ this.counter++; console.log(this.ref) } } } </script>
Now run this in your development server with the command:
npm run serve
Vue $refs
You will see that the user interface displays a simple counter that gets updated on click, but when you open your developer tools in the browser, you will notice that it logs undefined.
It is very important that you get the syntax right because this means that Vue does not see this as an error, but it is. According to what we already know about Vue ref
s, they return an object, but judging by the undefined response, something is wrong.
Copy the code below into the test.vue
file:
<template> <div> <h2>Hello this is for refs man!</h2> <p>You have counted {{this.counter}} times</p> <input type="text" ref="input"> <button @click="submit">Add 1 to counter</button> </div> </template> <script> export default { name: 'Test', data(){ return { counter: 0 } }, methods: { submit(){ this.counter++; console.log(this.$refs) } } } </script>
When you run this and inspect it, you will notice that it now returns an object:
A quick look at the code block will reveal the correct syntax: inside the template, it is called ref
, but when we refer to it in the Vue instance, it is called $refs
. This is very important to note to not get an undefined returned. The syntax ref
that’s used inside the template is an attribute given to an element. $refs
on the other hand, is a collection of the elements in your application that have been given the ref
attribute. You can access every single possible property of the referenced element, including the element as it is in the template.
Getting DOM elements in Vue.js
Let’s try logging some of the properties that might be of interest to us. Your test.vue
file should be:
<template> <div> <h2>Hello this is for refs man!</h2> <p>You have counted {{this.counter}} times</p> <input type="text" ref="input"> <button @click="submit">Add 1 to counter</button> </div> </template> <script> export default { name: 'Test', data(){ return { counter: 0 } }, methods: { submit(){ this.counter++; console.log(this.$refs) } } } </script> <style scoped> p , input, button{ font-size: 30px; } input, button{ font-size: 20px; } ul { list-style-type: none; padding: 0; } li { display: inline-block; margin: 0 10px; } a { color: #42b983; } </style>
The application on your browser should look like this:
Displaying HTML elements in Vue.js
To display the HTML element as it is in the DOM, go into the submit method and change the methods
code to the following:
methods: { submit(){ this.counter++; console.log(this.$refs.input) } }
The input here is the reference name you created earlier inside the element (ref="input"
). It can be any name of your choice.
Displaying the HTML input value
To display the HTML element input value — the string that was typed into the text box in the user interface — go into the submit
method and change the code to:
methods: { submit(){ this.counter++; console.log(this.$refs.input.value) } }
This displays exactly the string you type in, which shows a similarity to query selection which vanilla JavaScript and jQuery can achieve too.
Displaying a Vue element’s URL
The webpage in which the element can be found is also one of the many things that can be displayed with the Vue ref
. Go into the submit
method and change the code to this:
methods: { submit(){ this.counter++; console.log(this.$refs.input.baseURI) } }
There are many other things you can both access and log with the ref
just from information on the returned object.
Handling conditionals in Vue.js
Vue.js refs can also be used inside elements that output more than one element in the DOM, like conditional statements where v-for
directives are used. Instead of objects, ref
s return an array of the items when called. To illustrate this, create a simple list like this:
<template> <div> <p v-for="car in 4" v-bind:key="car" ref="car"> I am car number {{car}}</p> <button @click="submit">View refs</button> </div> </template> <script> export default { name: 'Test', data(){ return { } }, methods: { submit(){ console.log(this.$refs) } } } </script>
When you run it again in the development server, it will look like this:
Watching ref
s in Vue
Say you want to react to a change in a DOM element, like triggering a function when the value of an element changes. You can set up a watcher for this.
Below, we have a simple component with data:
const Name = { data: () => ({ myName: "Sam" }), }
We create the watcher inside the mounted
hook so that it only takes effect after the component has been rendered. We use the $watch()
instance method to watch for changes in the component’s data, myName
. When the value changes, the console.log
function is triggered.
<template> <div> <name ref="name" /> </div> </template> <script> export default { //... components: { Name }, mounted() { this.$watch( () => { return this.$refs.name.myName; }, (val) => { console.log(val); } ); }, //... }; </script>
You can find the full code of this tutorial on GitHub.
Conclusion
This post has exposed you to referencing HTML elements in your DOM in Vue.js. You can now both access and log these elements by all the element properties, including value, child node, data attributes, and even the base URL that houses it.
You have also been introduced to ways you can achieve this. It is important to note that ref
s get populated after the Vue instance has initialized and the component has been rendered, so using ref
s in computed properties is discouraged because it has the ability to directly manipulate child nodes. Happy hacking!
Experience your Vue apps exactly how a user does
Debugging Vue.js applications can be difficult, especially when there are dozens, if not hundreds of mutations during a user session. If you’re interested in monitoring and tracking Vue mutations for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording literally everything that happens in your Vue apps including network requests, JavaScript errors, performance problems, and much more. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred.
The LogRocket Vuex plugin logs Vuex mutations to the LogRocket console, giving you context around what led to an error, and what state the application was in when an issue occurred.
Modernize how you debug your Vue apps - Start monitoring for free.
thank you.