Home > Enterprise >  Vue js - ref within v-for loop always returning null
Vue js - ref within v-for loop always returning null

Time:03-10

I am trying to access an element in Vue as I want to see when it's class changes (I'm using Bootstrap so I want to watch for when a class changes to shown). The problem is that as soon as I put a ref'd element into a v-for loop it always returns null. I have tried appending the ref's name with the index of the loop item, and then trying to log this to the console it just always returns 'null'.

As soon as I take the element out of the v-for loop it returns the element fine.

I can't seem to find a solution. Is this something that Vue just simply doesn't support? If not, is there a better way for me to watch the DOM to see if an element's class changes?

P.S. I'm using the composition API.

Template:

<template>
    <div v-for="room in rooms" :key="room.id" >
        <p  :ref="'test' room.id">Hello world</p>
    </div>
</template

Script:

setup(){
      const test1 = ref(null)

      onMounted(() => {
          console.log("test1: ", test1.value)
      })

      return { test1 }
}

CodePudding user response:

This looks like a pretty common problem, so I went digging through the Vue source and found the following:

It's a limitation of the way Vue does updates and renders. If you have multiple s for the same template, then each of them has its own patch queue. Each patch queue gets processed on its own schedule, so it's possible for one to finish before another even starts. If that happens, then one of the queued updates won't happen. That would mean Vue wouldn't detect changes to your element and hence wouldn't do any re-rendering at all, which is why your element doesn't show up in your console output!

You can work around this by making sure all update queues finish before each other begins, which we can do by adding an update: { sync: true } config to your component in question. This will force Vue to process all of your update queues synchronously before processing any other changes in the application.

You could also add a sync: true config to your parent's component that wraps all of your other components and make sure they all sync.

<script>
  setup() {
    const test1 = ref(null)

    onMounted(() => {
      console.log("test1: ", test1.value)
    })

    return { test1 }
  }

  render() {
      return (
        <div>Hello World</div>
      )}

  </script>

CodePudding user response:

Template refs in a v-for

There's a known bug (vuejs/core#5525), where array refs are not properly populated.

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

                                  
  • Related