Search code examples
vue.jsvuejs3

Refs inside v-for Loop for vue v3.2.25 or above


I was reading the documentation of vue 3 and I decided to test refs in my local development environment. I am using vue version 3.2.31 and set up my project according to vue official guide. So for testing "refs" in my component, I just copied and pasted the code in this url that is the Playground of vue site. That means the code of my component is this:

<script setup>
import { ref, onMounted } from 'vue'

const list = ref([1, 2, 3])

const itemRefs = ref([])

onMounted(() => {
  console.log(itemRefs.value.map(i => i.textContent))
})
</script>

<template>
  <ul>
    <li v-for="item in list" ref="itemRefs">
      {{ item }}
    </li>
  </ul>
</template>

But in the console I receives an empty array. Am I missing something to do to see the output array of texts in li tags?


Solution

  • This is a known bug (vuejs/core#5525), where array refs are not properly populated.

    One workaround is to bind a function that pushes the template refs into the array instead:

    <template>
      <ul>                              👇
        <li v-for="item in list" :ref="el => itemRefs.push(el)">
          {{ item }}
        </li>
      </ul>
    </template>
    

    demo 1

    Or bind the ref array via a wrapper object (as suggested in the original issue):

    <script setup>
    import { ref, onMounted } from 'vue'
    
    const list = ref([1, 2, 3])
    
    const itemRefs = ref([])
              👇
    const skipUnwrap = { itemRefs }
    
    onMounted(() => {
      console.log(itemRefs.value.map(i => i.textContent))
    })
    </script>
    
    <template>
      <ul>                                 👇
        <li v-for="item in list" :ref="skipUnwrap.itemRefs">
          {{ item }}
        </li>
      </ul>
    </template>
    

    demo 2