How to Forward Refs with Vue 3 and <script setup>

under Vue

Forwarding refs in Vue 3 using the composition API and <script setup> isn't straight forward at first glance. There's two reasons for this:

  1. Vue automatically assigns template refs to the component instance the ref was passed to (obvious in hindsight).
  2. The component that was assigned the ref needs to explicitly declare which functions/properties it wants accessible via the parent.

defineExpose

The key to unlocking template ref forwarding is using Vue's defineExpose function to explicitly declare which functions/properties of the component should be accessible by the parent.

Here's a broken example that won't work due to no usage of defineExpose:

1// Child component
2<script setup>
3import { ref } from 'vue';
4 
5const count = ref(0);
6</script>
7 
8// Parent component
9<template>
10 <ChildComponent ref="countComponent" />
11</template>
12 
13<script setup>
14// the `countComponent` ref will be the instance of the `ChildComponent`
15const countComponent = ref(null);
16 
17 // This will not work because `ChildComponent` is not exposing `count`
18console.log('Current count: ', countComponent.value.count)
19</script>

The fix here is to have the child component expose count via defineExpose:

1// Child component
2<script setup>
3import { ref, defineExpose } from 'vue';
4 
5const count = ref(0);
6defineExpose({ count });
7</script>
8 
9// Parent component
10<template>
11 <ChildComponent ref="countComponent" />
12</template>
13 
14<script setup>
15// the `countComponent` ref will be the instance of the `ChildComponent`
16const countComponent = ref(null);
17 
18// This will now output 0
19console.log('Current count: ', countComponent.value.count);
20</script>

Thanks for reading this article!

Hopefully you found this article useful! If you did, share it on Twitter!

Found an issue with the article? Submit your edits against the repository.