File tree Expand file tree Collapse file tree 5 files changed +67
-2
lines changed Expand file tree Collapse file tree 5 files changed +67
-2
lines changed Original file line number Diff line number Diff line change
1
+ import { nodeOps , render } from '@vue/runtime-test'
2
+ import { h , expose , ref } from '../src'
3
+
4
+ describe ( 'api: expose' , ( ) => {
5
+ test ( 'component ref should only expose exposed properties' , ( ) => {
6
+ const Child = {
7
+ render ( ) { } ,
8
+ setup ( ) {
9
+ expose ( {
10
+ foo : ref ( 1 ) ,
11
+ bar : ref ( 2 )
12
+ } )
13
+ return {
14
+ bar : ref ( 3 ) ,
15
+ baz : ref ( 4 )
16
+ }
17
+ }
18
+ }
19
+ const childRef = ref ( )
20
+ const Parent = {
21
+ setup ( ) {
22
+ return ( ) => h ( Child , { ref : childRef } )
23
+ }
24
+ }
25
+ const root = nodeOps . createElement ( 'div' )
26
+ render ( h ( Parent ) , root )
27
+ expect ( childRef . value ) . toBeTruthy ( )
28
+ expect ( childRef . value . foo ) . toBe ( 1 )
29
+ expect ( childRef . value . bar ) . toBe ( 2 )
30
+ expect ( childRef . value . baz ) . toBeUndefined ( )
31
+ } )
32
+
33
+ test ( 'expose called outside of setup()' , ( ) => {
34
+ expose ( { } )
35
+ expect (
36
+ `expose() is called when there is no active component instance`
37
+ ) . toHaveBeenWarned ( )
38
+ } )
39
+ } )
Original file line number Diff line number Diff line change
1
+ import { proxyRefs } from '@vue/reactivity'
2
+ import { getCurrentInstance } from './component'
3
+ import { warn } from './warning'
4
+
5
+ // TODO: refine and merge RFC (https://github.com/vuejs/rfcs/pull/210)
6
+ // TODO: corresponding option (https://github.com/vuejs/rfcs/pull/135)
7
+
8
+ export function expose ( values : Record < string , any > ) {
9
+ const instance = getCurrentInstance ( )
10
+ if ( instance ) {
11
+ Object . assign (
12
+ instance . exposed || ( instance . exposed = proxyRefs ( { } ) ) ,
13
+ values
14
+ )
15
+ } else if ( __DEV__ ) {
16
+ warn (
17
+ `expose() is called when there is no active component instance to be ` +
18
+ `associated with.`
19
+ )
20
+ }
21
+ }
Original file line number Diff line number Diff line change @@ -270,6 +270,9 @@ export interface ComponentInternalInstance {
270
270
// main proxy that serves as the public instance (`this`)
271
271
proxy : ComponentPublicInstance | null
272
272
273
+ // exposed properties via expose()
274
+ exposed : Record < string , any > | null
275
+
273
276
/**
274
277
* alternative proxy used only for runtime-compiled render functions using
275
278
* `with` block
@@ -416,6 +419,7 @@ export function createComponentInstance(
416
419
render : null ,
417
420
proxy : null ,
418
421
withProxy : null ,
422
+ exposed : null ,
419
423
effects : null ,
420
424
provides : parent ? parent . provides : Object . create ( appContext . provides ) ,
421
425
accessCache : null ! ,
Original file line number Diff line number Diff line change @@ -40,6 +40,7 @@ export {
40
40
onErrorCaptured
41
41
} from './apiLifecycle'
42
42
export { provide , inject } from './apiInject'
43
+ export { expose } from './apiExpose'
43
44
export { nextTick } from './scheduler'
44
45
export { defineComponent } from './apiDefineComponent'
45
46
export { defineAsyncComponent } from './apiAsyncComponent'
Original file line number Diff line number Diff line change @@ -300,12 +300,12 @@ export const setRef = (
300
300
return
301
301
}
302
302
303
- let value : ComponentPublicInstance | RendererNode | null
303
+ let value : ComponentPublicInstance | RendererNode | Record < string , any > | null
304
304
if ( ! vnode ) {
305
305
value = null
306
306
} else {
307
307
if ( vnode . shapeFlag & ShapeFlags . STATEFUL_COMPONENT ) {
308
- value = vnode . component ! . proxy
308
+ value = vnode . component ! . exposed || vnode . component ! . proxy
309
309
} else {
310
310
value = vnode . el
311
311
}
You can’t perform that action at this time.
0 commit comments