Expose API discussion (#343) #345
Replies: 6 comments 12 replies
-
I am so glad What will happen if we try to access private component methods? If an A perfect example here is Composition API where an author can severely limit what can be accessed by parent components. Let's say we are bound to a library that doesn't emit event while it could. In Options API we could subscribe to some of its internal data or methods and simulate these events. With Composition API that interface is hidden from us and there's nothing we could do about that. I would really like for Options API to retain the current level of flexibility along with improved developer experience. How state mutations are going to be affected? Let's say we exposed some internal component's state to the parent component and our parent component mutates that state via Should Vue warn that exposed member is undefined? A common scenario with Public API is that it might get removed by accident because it's not used by the component itself. Maybe that's a good idea to notifiy developers as soon as it gets removed? |
Beta Was this translation helpful? Give feedback.
-
Just tried this, seems a public instance with explicit |
Beta Was this translation helpful? Give feedback.
-
This RFC is now in final comments stage. An RFC in final comments stage means that: The core team has reviewed the feedback and reached consensus about the general direction of the RFC and believe that this RFC is a worthwhile addition to the framework. |
Beta Was this translation helpful? Give feedback.
-
Really small detail, but there is a typo in 2 of the snippets: |
Beta Was this translation helpful? Give feedback.
-
This RFC has been merged. |
Beta Was this translation helpful? Give feedback.
-
expose()
public members #210Summary
Provide the ability for components to control what is publicly exposed on its component instance. This proposal unifies #135 and #210 with additional details.
Basic example
Options API
Composition API
Here in the both cases, other components would only be able to access the
increment
method from this component, and nothing else.Motivation
In Vue, we have a few ways to retrieve the "public instance" of a component:
$parent
or$root
propertiesUp until now, the concept of the "public instance" equivalent to the
this
context inside a component. However, this creates a number of issues:A component's public and internal interface isn't always the same. A component may have internal properties that it doesn't want to expose to other components, or a component may want to expose methods that are specifically meant to be used by other components.
A component returning render function from
setup()
encloses all its state inside thesetup()
closure, so nothing is exposed on the public instance, and there's currently no way to selectively expose properties while using this pattern.<script setup>
is also compiled into (2) so has the same issue.The proposed APIs solve these issues by giving components the ability to explicitly declare publicly exposed properties.
Detailed design
Options API
A new option,
expose
is introduced. It expects an array of property keys to be exposed:In a parent component:
If
expose
is an empty array, then the component would be considered "closed" and no properties would be exposed.Composition API
In Composition API, the 2nd argument of
setup
(aka the "setup context") now also provides theexpose
method:The
expose
method expects an object of the actual values to be exposed.In
<script setup>
The
defineExpose()
macro compiles into runtimeexpose()
call.See relevant section in the
<script setup>
RFC.Exposed Ref Unwrapping Behavior
Note the exposed instance unwraps refs similar to the normal public instance:
Limiting Expose Control to Base Component
As raised in the discussions for a previous draft (#210), it would be very confusing if mixins and external composition functions are able to expose arbitrary properties. Therefore, the API is designed to restrict the capability to the base component only:
expose
option is ignored when encountered inmixins
orextends
sources.expose
function is provided via the setup context instead of a global API (so that it cannot be imported in external composition functions) and can only be called once.Additionally Exposed Properties
An experimental implementation has been shipped in prior versions and we found in some cases there are patterns or tools (e.g.
vue-test-utils
) that relies on the presence of Vue built-in instance properties like$el
or$refs
.The public instance with explicit
expose
thus still exposes these built-in instance properties.Drawbacks
N/A
Alternatives
N/A
Adoption strategy
This feature is additive and doesn't affect existing usage.
Unresolved Questions
Type Inference
Currently no Vue tooling has the ability to infer types of child component instances obtained from a ref.
A workaround is to explicitly export the public interface from the child component:
In parent:
The above does not affect the runtime API design and therefore should not block this RFC from being merged.
Beta Was this translation helpful? Give feedback.
All reactions