skip to Main Content

I need to convert the below piece of code in Vue 3 Composition API so I can get the position of the element. Currently I tried converting this but its not at all working out. Please if someone can shed some light on this.

<template>
  <div>
    <div v-for="index in divs" :key="index">
      <div :ref="'ref_' + index" @mouseover="divDragOver($event, index)">
        This is div {{ index }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
  data: () => ({
    divs: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
  }),
  methods: {
    divDragOver(e, i) {
      let [div] = this.$refs['ref_' + i];
      let top = div.getBoundingClientRect().top;
      console.log(top);
    },
  },
};
</script>

This is what I am trying to do, but I am unable to figure this out.

<template>
  <div>
    <div v-for="index in divs" :key="index">
      <div :ref="'ref_' + index" @mouseover="divDragOver($event, index)">
        This is div {{ index }}
      </div>
    </div>
  </div>
</template>

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

  const divs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

  function divDragOver(e, i) {
    let itemRefs = ['ref_' + i]
    let top = itemRefs.getBoundingClientRect().top
    console.log(top)
  }
</script>

Would really like to thank the community for the help and support.

2

Answers


  1. After a bit of tinkering around, I refactored your code to tame it composition API way. The problem here is that you are trying to call the getBoundingClientRect() method on a string array, which is not possible since it’s not an actual DOM element.

    Using :ref="el => (divRefs[index] = el)" does the magic you want there. Then the rest of the logic is similar to what you’ve done already.

    <template>
      <div>
        <div v-for="index in divs" :key="index">
          <div :ref="el => (divRefs[index] = el)" @mouseover="divDragOver($event, index)">
            This is div {{ index }}
          </div>
        </div>
      </div>
    </template>
    
    <script setup>
    import { ref } from 'vue'
    
    const divs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    const divRefs = {}
    
    function divDragOver(e, i) {
      let itemRef = divRefs[i]
      if (itemRef) {
        let top = itemRef.getBoundingClientRect().top
        console.log(top)
      }
    }
    </script>
    

    Sandbox for testing: https://codesandbox.io/s/nostalgic-knuth-vdwmp8?file=/src/App.vue:0-499

    Login or Signup to reply.
  2. As i said in the comment, you need to use function refs

    So, in the code below, we first set up a variable, lets say const refs = ref([])

    Then, the "function ref" is written like :ref="(el) => refs[index] = el" as per the documentation

    Now to access the ref … let itemRef = refs.value[i];

    Full code:

    <script setup>
    import { ref } from 'vue'
    
      const divs = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      const refs = ref([]);
      function divDragOver(e, i) {
        let itemRef = refs.value[i];
        let top = itemRef.getBoundingClientRect().top
        console.log(top)
      }
    </script>
    
    <template>
      <div>
        <div v-for="index in divs" :key="index">
          <div :ref="(el) => refs[index] = el" @mouseover="divDragOver($event, index)">
            This is div {{ index }}
          </div>
        </div>
      </div>
    </template>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search