An Introduction To Vue $refs
The $refs property in Vue is used to reference DOM elements in the Vue instance's templates.
A common use case for $refs is focusing on a DOM element when a certain event happens. The autofocus property works on page loads. But what if you want to give focus back to the username input if login failed?
If you give the username input a ref attribute in your template, you can then access
the username input using this.$refs.username as shown below. You can then call
the built-in Element#focus() function to give focus to the username input.
const app = new Vue({
data: () => ({ username: '', password: '', failed: false }),
methods: {
login: async function() {
// Simulate that login always fails, just for this example
this.failed = true;
// Give focus back to `username` input. If you change the
// 'ref' attribute in the template to 'usernameRef', you
// would do `this.$refs.usernameRef` here.
this.$refs.username.focus();
}
},
template: `
<div>
<input type="text" v-model="username" ref="username" id="username">
<input type="password" v-model="password">
<button v-on:click="login()">Login</button>
<div v-if="failed" id="failed">
Login Failed!
</div>
</div>
`
});
With v-for
When you use ref with the v-for directive,
Vue gives you a native JavaScript array of elements, not just a single element.
For example, suppose you have a list of <input> tags, and you want users
to be able to navigate between inputs using the up and down arrow keys.
You can access the individual <input> elements using $refs and call
focus() whenever the user presses up or down:
const app = new Vue({
data: () => ({ cells: ['foo', 'bar', 'baz'].map(val => ({ val })) }),
mounted: function() {
let cur = 0;
this.$refs.inputs[0].focus();
document.addEventListener('keyup', ev => {
console.log('Got event', ev)
cur = this.$refs.inputs.findIndex(el => document.activeElement === el);
if (cur === -1) {
cur = 0;
}
const numEls = this.cells.length;
if (ev.keyCode === 38) { // Up arrow
cur = (numEls + cur - 1) % numEls;
this.$refs.inputs[cur].focus();
} else if (ev.keyCode === 40) { // Down arrow
cur = (cur + 1) % numEls;
this.$refs.inputs[cur].focus();
}
});
},
template: `
<div>
<div v-for="cell in cells">
<input v-model="cell.val" ref="inputs">
</div>
</div>
`
});