Vue.js ref inside the v-for loop
When using refs with v-for, the component / DOM nodes are stored as an array directly to the variable name so you don't need to use index number in the ref name. So you can do this:
<list-item
v-for="item in items"
:key="item.id"
:value="item.text"
ref="items"
/>
And use the refs in your component like this:
this.$refs.items[index]
Also note that the refs may not be in order and would need to be handled in a different way which is a completely different issue. You can follow that here: https://github.com/vuejs/vue/issues/4952
For Vue 3 users:
In Vue 3, such usage will no longer automatically create an array in $refs
. To retrieve multiple refs from a single binding, bind ref
to a function which provides more flexibility (this is a new feature):
HTML
<div v-for="item in list" :ref="setItemRef"></div>
With Options API:
export default {
data() {
return {
itemRefs: []
}
},
methods: {
setItemRef(el) {
if (el) {
this.itemRefs.push(el)
}
}
},
beforeUpdate() {
this.itemRefs = []
},
updated() {
console.log(this.itemRefs)
}
}
With Composition API:
import { onBeforeUpdate, onUpdated } from 'vue'
export default {
setup() {
let itemRefs = []
const setItemRef = el => {
if (el) {
itemRefs.push(el)
}
}
onBeforeUpdate(() => {
itemRefs = []
})
onUpdated(() => {
console.log(itemRefs)
})
return {
setItemRef
}
}
}
Here is the doc link: https://v3.vuejs.org/guide/migration/array-refs.html
I tried to handle refs inside v-for by passing index from method:
<div v-for="(item, index) in items" @click="toggle(index)">
<p ref="someRef"></p>
</div>
toggle(index) {
this.refs['someRef'][index].toggle();
}
But in reality it was toggling the wrong elements as indexes of refs are not ordered.
So what I did is added data attribute to ref elements:
<div v-for="(item, index) in items" @click="toggle(index)">
<p ref="someRef" :data-key="index"></p>
</div>
Now each ref has its specific data-key. And can be toggled like this:
toggle(index) {
const dropdown = this.$refs['someRef'].find(
el => el.$attrs['data-key'] === index
);
dropdown.toggle();
}
I had faced the same issue.
As sobolevon mentioned, the returning value of $refs.{ref name}
is an array in v-for refs, so my solution is to consider $refs.{ref name}
is an array with one item only by default, and write $refs.{ref name}[0].methodToCall()
.
And it works for my case.