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.