This post is going to explain how to use Ref in Vue 3, while using the Composition API and the Script Setup. The usage of references when using the options API is unchanged, but Vue 3 provided us with two different ways to define the component script block, Composition API and Script Setup.
In the first part of this article, we are going to introduce Refs, but if you are already familiar with this feature and you just want to know how to use Ref with the Composition API or the Script Setup, you can jump to the section called: Ref in Composition API example or Ref in Script Setup example respectively.
What are $refs in Vue
In Vue js, $refs
provide you with the ability to access the DOM element of a specific HTML element or custom component available within your template.
In simple words, applying the ref
attribute to a specific element in your template, give you the ability to obtain a direct reference DOM element, this is the same result that you would get when using document.getElementById
, document.getElementByClassName
or any other similar API resource.
When would you use $refs
Accessing DOM references of HTML elements is not very common during your day-to-day activities, but it is an important feature to learn. Being able to use refs successfully unlocks a full set of implementation, bringing your development skills to another level.
It is important to clarify that refs should not be used unless strictly necessary. Using DOM manipulation can be costly, and when possible it is always suggested to use the existing Vue APIs to try and achieve your needs (props, data, and computed).
Here are a few examples that would require you to access the DOM element using $refs
:
- Having to focus on a component after a specific event but calling
- Having to change specific styles that cannot easily be handled by classes ( this should not be handled using v-bind in CSS see this post for details: https://zelig880.com/how-to-use-variables-in-css-with-v-bind-in-vuejs-3 )
- Having to fetch specific information of the element, such as height or offset values.
How to use $refs with Composition API
It is now time to learn how to use this feature while using the Composition API. If you have been using the Options API and have previously used this feature, you know that an object was available within the component context (accessible with this) and all refs were stored with the this.$refs
object.
In the Composition API and Script Setup, we have not only lost access to the context
, but also lost the ability to access the $refs
object.
An HTML reference using the Composition API is defined the same way you would define any other variable using the syntax const variableName = ref(null)
.
Usage of DOM reference requires two steps. First, you would declare a variable, initializing it to null, then you need to assign that variable name as a “ref” attribute on the element.
Let’s write two simple example, for the Composition API and the Script Setup respectively
Ref in Composition API example
<script>
import { ref } from "vue";
export default {
setup() {
const myReference = ref(null);
return {
myReference
};
}
};
</script>
<template>
<h1 ref="myReference">I have access to the DOM reference now</h1>
</template>
Ref in Script Setup example
<script setup>
import { ref } from "vue";
const myReference = ref(null);
</script>
<template>
<h1 ref="myReference">I have access to the DOM reference now</h1>
</template>
The use of this feature is quite simple and even if we have lots of access to the $refs object, we are still able to make use of DOM element quite easily. In the next section, we are going to use this method and understand how it is defined and updated during the Vue lifecycles
Why is the ref null in the setup function?
In this section, we are going to answer an important question that may arise quite quickly after you try to use the Ref feature of Vue js. I have personally fallen for this simple detail and I wanted to make sure we cover it in detail in this post.
If we would try to access our variable within the setup function, we would be quite disappointed as it will result in a null
response:
<script setup>
import { ref } from "vue";
const myReference = ref(null);
console.log(myReference.value); <-- This will output null
</script>
<template>
<h1 ref="myReference">I have access to the DOM reference now</h1>
</template>
The reason behind this behaviour is plainly explained in the Vue documentation (I am not sure how I missed it), but it states:
(talking about refs) It allows us to obtain a direct reference to a specific DOM element or child component instance after it’s mounted.
https://vuejs.org/guide/essentials/template-refs.html
A reference cannot be accessed until the component is mounted, because that is the lifecycle that handles the creation of the HTML. When trying to access the variable directly, as I did in the example above, would have triggered the console.log
even before the “beforeCreated” is reached as explained in the lifecycle Hooks documentation.
To be able to access our reference we need to make sure that the component is actually rendered, therefore call our method within the “onMounted” hook:
<script setup>
import { ref, onMounted } from "vue";
const myReference = ref(null);
onMounted(() => {
console.log(myReference.value); <-- This will output a DOM node
})
</script>
<template>
<h1 ref="myReference">I have access to the DOM reference now</h1>
</template>
Summary
Even if things have changed since the Options API, the syntax required to access the DOM elements is still quite simple. The Vue core team has done a fantastic job of really making things simple while providing a very powerful API.
As I already mentioned above, accessing the DOM node directly can be costly and should just be done when no other options are available.