vue.jsvuejs3vue-script-setupsubcomponent

defineExpose from component's <script setup> not working in vue 3


New to Vue in general and currently using 3.2.37, I possibly missunderstood the correct usage of composition api’s defineExpose directive as documented here: https://vuejs.org/api/sfc-script-setup.html#defineexpose

There are also some threads to be found, explaining how to expose members from inside <script setup> like Calling method on Child Component - Composition API. But somehow I cannot manage to expose the version constant ref from child component HelloWorld so that it's version can be interpolated in app component.

app.vue:

<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>

<template>
  <main>
    <HelloWorld />
    <h1>version:{{HelloWorld.version}}</h1>
  </main>
</template>

HelloWorld.vue:

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

const version = ref('1.0.0');

defineExpose({ version });
</script>

<template>
    <div>
        <h3> You’ve successfully created a project with Vue.js and Vuetify. </h3>
    </div>
</template>

Image: version 1.0.0 not showing


Solution

  • you can check this website...

    Components using Options API or Composition API without are open by default.

    If we try to access the public instance of such a component via template ref or $parent chains, it will not expose any of the bindings declared inside the block.

    We can use the defineExpose compiler macro to explicitly expose properties:

    Child.vue

    <script setup>
    import { ref } from 'vue'
    const foo = ref('foo')
    const bar = ref('bar')
    defineExpose({
      foo,
      bar,
    })
    </script>
    

    When a parent gets an instance of Child.vue via template ref, the retrieved instance will be of the shape { foo: string, bar: string } (refs are automatically unwrapped just like on normal instances):

    Parent.vue

    <template>
      <Child ref="child" />
    </template>
    <script setup>
    import { ref } from 'vue'
    const child = ref(null);
    
    onMounted(() => {
      console.log(child.value.foo)
      console.log(child.value.bar)
    })
    
    </script>