Vue gives us a lot of powerful features when it comes to manipulating the DOM. It simplifies the job of maintaining states, to create UIs which are easy to maintain, and fun to use. One thing Vue does really well, is removes the need for direct DOM manipulation. Sometimes, though, we still need to manipulate or reference DOM elements themselves. Fortunately, Vue has thought of this, and allows us to do this with the ref attribute.
Referencing DOM Elements in Vue
Although it's certainly possible to use .querySelector() on a Vue document, it's not best practice. If we want to reference a DOM element, we can use the ref attribute in Vue.
Let's look at a quick example. Below, we have our App.vue page, which has an input, and we want to reference that input directly in one of our methods:
<template>
<button id="myButton">Some Button</button>
</template>
<script>
export default {
mounted: function() {
}
}
</script>
<style scoped>
button {
background: black;
color: white;
border: none;
border-radius: 4px;
}
</style>
Vue can store references to DOM elements in a property called $ref. The first thing we have to do, is add a ref attribute to the element we want to reference in our Javascript. The value of the ref attribute will be the name of it within the $ref property.
For mine, I am calling it myButton:
<template>
<button id="myButton" ref="myButton"></button>
</template>
Next, in our Javascript, we can call upon that reference, as shown below:
export default {
mounted: function() {
console.log(this.$ref.myButton);
}
This will return the DOM element itself - so you can manipulate it like you'd manipulate any DOM element.
How to use Vue references to return a DOM element
Referencing Child Components
If our button was a component, we could also access it using the same ideas. For example suppose we have a child component, called TestComponent. We can add a ref directly to the child component, as shown below:
<template>
<button id="myButton" ref="myButton">Some Button</button>
<TestComponent ref="anotherButton">
</template>
<script>
import TestComponent from '../components/TestComponent.vue';
export default {
components: {
TestComponent
},
mounted: function() {
// Console logs our "myButton"
console.log(this.$refs.myButton);
// Console logs "anotherButton"
console.log(this.$refs.anotherButton);
}
}
</script>
<style scoped>
button {
background: black;
color: white;
border: none;
border-radius: 4px;
}
</style>
Above, we add ref to the component itself:
<TestComponent ref="anotherButton" />
The difference here, is that it doesn't return the DOM element itself - it instead returns an object for the child component.
Referencing a Child Component's DOM element
Since we get an object for a child component when using references, if we want to access the DOM element within a child component itself, we have to use $el - which will refer to the DOM element in the component itself.
// This is the child component reference
this.$refs.anotherButton
// This is the DOM element for the component
this.$refs.anotherButton.$el
Referencing a Child Component's Method
Since a referencing a child component refers to the entire component, we can reference its methods using this reference. Let's say our child component has Javascript that looks like the code below.
TestComponent.vue:
<script>
export default {
methods: {
someFunction: function() {
console.log('Hello');
}
}
}
</script>
In our main, App.vue file, we can reference this method through our reference. For example:
<template>
<button id="myButton" ref="myButton">Some Button</button>
<TestComponent ref="anotherButton">
</template>
<script>
import TestComponent from '../components/TestComponent.vue';
export default {
components: {
TestComponent
},
mounted: function() {
this.$refs.anotherButton.someFunction();
}
}
</script>
<style scoped>
button {
background: black;
color: white;
border: none;
border-radius: 4px;
}
</style>
Above, since we have added a reference ref="anotherButton" to the child component, we can reference it in our Javascript through that reference. All methods are available through this reference:
this.$refs.anotherButton.someFunction();
Using References with v-for
The same concepts apply to v-for
. If you use a ref on a v-for element, each element produced by the v-for loop, will be returned as an array within that reference.
For example, let's say we have the following code:
<template>
<ul>
<li v-for="(item, index) in locations" :key="index" ref="myLocations">{{ item.name }}</li>
</ul>
</template>
<script>
export default {
data() {
return {
locations: [
{ name: 'London', date: '11/02/2022' },
{ name: 'Paris', date: '12/01/2022' },
{ name: 'Tokyo', date: '04/06/2021' }
]
}
},
mounted: function() {
let liElements = this.$refs.myLocations;
console.log(liElements);
}
}
</script>
<style scoped>
button {
background: black;
color: white;
border: none;
border-radius: 4px;
}
</style>
Since we've added a ref called myLocations to our li element, we can now access it via this.$refs.myLocation. Since it is also a v-for, myLocation will be an array. To get the second li element, we would do the following:
this.$refs.myLocations[1];
Conclusion
References in Vue are a powerful way to access the DOM elements that Vue produces. They are also the best way to do it when working within the Vue framework. I hope you've enjoyed this article. For more Vue content, you can find it here.