Skip to content

Commit

Permalink
feat(runtime-core): add expose() API
Browse files Browse the repository at this point in the history
WIP - ref: vuejs/rfcs#210
  • Loading branch information
yyx990803 committed Sep 16, 2020
1 parent c7b4a37 commit c6033fb
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 2 deletions.
39 changes: 39 additions & 0 deletions packages/runtime-core/__tests__/apiExposed.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { nodeOps, render } from '@vue/runtime-test'
import { h, expose, ref } from '../src'

describe('api: expose', () => {
test('component ref should only expose exposed properties', () => {
const Child = {
render() {},
setup() {
expose({
foo: ref(1),
bar: ref(2)
})
return {
bar: ref(3),
baz: ref(4)
}
}
}
const childRef = ref()
const Parent = {
setup() {
return () => h(Child, { ref: childRef })
}
}
const root = nodeOps.createElement('div')
render(h(Parent), root)
expect(childRef.value).toBeTruthy()
expect(childRef.value.foo).toBe(1)
expect(childRef.value.bar).toBe(2)
expect(childRef.value.baz).toBeUndefined()
})

test('expose called outside of setup()', () => {
expose({})
expect(
`expose() is called when there is no active component instance`
).toHaveBeenWarned()
})
})
21 changes: 21 additions & 0 deletions packages/runtime-core/src/apiExpose.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { proxyRefs } from '@vue/reactivity'
import { getCurrentInstance } from './component'
import { warn } from './warning'

// TODO: refine and merge RFC (https://github.com/vuejs/rfcs/pull/210)
// TODO: corresponding option (https://github.com/vuejs/rfcs/pull/135)

export function expose(values: Record<string, any>) {
const instance = getCurrentInstance()
if (instance) {
Object.assign(
instance.exposed || (instance.exposed = proxyRefs({})),
values
)
} else if (__DEV__) {
warn(
`expose() is called when there is no active component instance to be ` +
`associated with.`
)
}
}
4 changes: 4 additions & 0 deletions packages/runtime-core/src/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,9 @@ export interface ComponentInternalInstance {
// main proxy that serves as the public instance (`this`)
proxy: ComponentPublicInstance | null

// exposed properties via expose()
exposed: Record<string, any> | null

/**
* alternative proxy used only for runtime-compiled render functions using
* `with` block
Expand Down Expand Up @@ -416,6 +419,7 @@ export function createComponentInstance(
render: null,
proxy: null,
withProxy: null,
exposed: null,
effects: null,
provides: parent ? parent.provides : Object.create(appContext.provides),
accessCache: null!,
Expand Down
1 change: 1 addition & 0 deletions packages/runtime-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export {
onErrorCaptured
} from './apiLifecycle'
export { provide, inject } from './apiInject'
export { expose } from './apiExpose'
export { nextTick } from './scheduler'
export { defineComponent } from './apiDefineComponent'
export { defineAsyncComponent } from './apiAsyncComponent'
Expand Down
4 changes: 2 additions & 2 deletions packages/runtime-core/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,12 +300,12 @@ export const setRef = (
return
}

let value: ComponentPublicInstance | RendererNode | null
let value: ComponentPublicInstance | RendererNode | Record<string, any> | null
if (!vnode) {
value = null
} else {
if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) {
value = vnode.component!.proxy
value = vnode.component!.exposed || vnode.component!.proxy
} else {
value = vnode.el
}
Expand Down

0 comments on commit c6033fb

Please sign in to comment.