DEV Community

Cover image for Dynamic Refs in Vue3 The Right Way
Waleed Asender
Waleed Asender

Posted on • Updated on

Dynamic Refs in Vue3 The Right Way

Understanding Refs

Refs in Vue are a way to access and manipulate DOM elements or component instances. You may consider it as the Vue replacement for getElementById.

Instead of writing:

<script>
  const commentCard = document.getElementById('comment-card');
</script>

<div id="comment-card">...</div>
Enter fullscreen mode Exit fullscreen mode

in Vue you will write:

<script>
  const commentCard = ref(null);
</script>

<div ref="comment-card">...</div>
Enter fullscreen mode Exit fullscreen mode

then you can manipulate the element commentCard as you wish.

The Pitfall of Static Refs

Unfortunately, In many cases, static refs are bound to a specific element or component during initialization. This can become problematic when dealing with dynamic UIs where elements are created or removed based on dynamic fetched data.

Scenario

Let's say we have a blog with comment list, and we want to reference each comment DOM, but this comment list is dynamic and we don't know how many comments will be there:

<template v-for="comment in comments" :key="comment.id">
  <CommentCard
    :commentId="comment.id"
    :ref="`commentCard${comment.id}`"
  />
</template>
Enter fullscreen mode Exit fullscreen mode

If we need for any reason to manipulate these elements or components it will be difficult to reference them using static Refs commentCard1, commentCard2, commentCard3 ..., we will need to bound the whole block with a parent Ref then call a function to refresh the list of child elements every time we want to interact with it, this will cause performance issues and may fail in some cases.

Solution

Instead of defining static Refs, we need to generate dynamic Refs for the element in the loop in as callback, and assign them to a Vue object variable using 'Function Refs':

<script>
  import { ref } from "vue";
  const commentCardRef = ref({});
</script>

<template v-for="comment in comments" :key="comment.id">
  <CommentCard
    :commentId="comment.id"
    :ref="(el) => (commentCardRef[comment.id] = el)"
  />
</template>
Enter fullscreen mode Exit fullscreen mode

This means we'll collect the Ref of each created DOM element in the loop and store them in this object. This gives us easy access to all the DOMs, letting us change them using their assigned Ids:

commentCardRef.value[comment.id];
Enter fullscreen mode Exit fullscreen mode

Thanks for reading! I hope this method help you in your development work.

Top comments (0)