Skip to content

Inconsistent component ref when using defineExpose #9136

@perenstrom

Description

@perenstrom

Vue version

3.3.4

Link to minimal reproduction

https://play.vuejs.org/#eNrVVEtv2zAM/iuEL3GBxMbanTI36B4F1mFYi67YLr54Nv3oZEmQ5DRFlv8+SnJSO2mBPQ+9CBIfIj/yI9fBaymjZYfBPEh0rhppQKPpJLCMV6dpYHQaLFLetFIoA2tQWE7hLjN5DRsolWhhQt6TncVb0cpeHsX2YT+fvBrpvzamPl9JoXFk+SDe+qQ8F1x7J8GRm2ssX8CpTSK5IEXGc7y5l5gYOkTp7BbwA3jH2CK05xH94rINR39MIVxm7AhOF7BOOYANIxhGTFRhGnwUVdXwCtr7KyV6NKZGsuq/6KtQoxoK312ef/40uYE6WyIUWDYcPZx5Gtg8xmEofuQDWN3GHo/BPf4HcI//G9y/wZrEnm/ELqCXwVayzKB9QuJoRGGJgaPGpUGfJineI2OCBPGDy4BZh87HB85WYr2TeBc9mAaeqbM2k9GtFpwmwxUt7RU0EHNfRisjptp3GtTGSD2P47zg5FYga5Yq4mhiLtv4jMxi1XHTtDgrRHt2Ep1EL+Oi0WYojlC3s29K3GlU9EkaTAdhYhIuUc0U8oI6oX417J7bMPSe6iC8jb6hhlFRjKaGlk21VxJLh4ahupSmoYaPSpNRhe8+OJlRHe6w5DXm3x+R3+qVx3Sl0GU2wG8yVaHxapoyXNF9p2xF0bG+DU8or5HI2NkcvdmbjheU9sDOZXvhOkzDcKPPVwa53oKyibpqOHvXD0utp6A/pEvVHlRxuxB/Y9uO1qwbHCSCk7bhBlWZ5QiW0nob3DN8DtoowmHHzfr4EXWGiTsX4XDjtPdfMtah3zVhmTGNVj0Y0f0JBVivtxtjQyHGI3S4zp8J4q2fTzy0EL2dW1p/WI/NTy+bkoY=

Steps to reproduce

The exposed vue instance when adding a ref to a Vue component in Script Setup differs if you have defined exposes with defineExpose().

Create two components, which take a single prop, identical except that one has a defineExpose.

Import these components in a parent component, and set a ref on them. Then log that ref's value.myProp (in a watcher, or onmounted).

What is expected?

The two logs log the same value.

What is actually happening?

If you do not have a defineExpose in your component, a parent component can access the props sent to that component via myRef.value.myProp, but as soon as you define exposes in the component, myRef.value.myProp returns undefined.

System Info

No response

Any additional comments?

The documentation for defineExpose (https://vuejs.org/api/sfc-script-setup.html#defineexpose) doesn't mention anything about that using it change the behaviour of other properties on the ref. So either it seems the documentation is unclear and needs to be clarified, or it is indeed a bug.

Activity

linghaoSu

linghaoSu commented on Sep 5, 2023

@linghaoSu
Contributor

defineExpose in the setup script is macro syntax, so it will compile to the expose call in the setup function.
image

In the setup function docs, we will see that the expose function call will "close" the current instance, exposing only the incoming parameters for external access .

image

Without defineExpose, it's as if nothing is returned in the setup function

full demo with setup function

perenstrom

perenstrom commented on Sep 5, 2023

@perenstrom
Author

Right, thanks for the explanation. I still however believe that the docs are lacking in this case.

From the docs for <script setup> it says that these are "closed by default", which doesn't seem to be the case? As per my reproduction link. I take this to mean the same as calling expose(); in the setup() function.

CleanShot 2023-09-05 at 18 53 26@2x
LinusBorg

LinusBorg commented on Sep 6, 2023

@LinusBorg
Member

you're right in that script setup components are designed to always to be closed. And they are in DEV mode (switch the playground from PROD to DEV (button in the upper right) and it works as you expect it to.

It seems that components compiled for prod do not generate the expose proxy, which seems like a bug to me.

perenstrom

perenstrom commented on Sep 7, 2023

@perenstrom
Author

Oh, right! That makes sense then why we encountered it. We encountered it in dev mode (in project A) since the anomaly occurred in our built and packaged internal component library (in project B)! So an edge case for sure. Swift fix by @baiwusanyu-c !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Participants

      @perenstrom@LinusBorg@linghaoSu

      Issue actions

        Inconsistent component ref when using `defineExpose` · Issue #9136 · vuejs/core