diff --git a/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx b/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx index 9e7420ae..a2775d4c 100644 --- a/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx +++ b/packages/runtime-core/__tests__/apiCreateComponent.spec.tsx @@ -41,7 +41,8 @@ test('createComponent type inference', () => { } } }, - render(props) { + render() { + const props = this.$props props.a && props.a * 2 props.b.slice() props.bb.slice() @@ -68,9 +69,9 @@ test('type inference w/ optional props declaration', () => { a: 1 } }, - render(ctx) { - ctx.msg - ctx.a * 2 + render() { + this.$props.msg + this.$data.a * 2 this.msg this.a * 2 } @@ -95,10 +96,10 @@ test('type inference w/ array props declaration', () => { c: 1 } }, - render(ctx) { - ctx.a - ctx.b - ctx.c + render() { + this.$props.a + this.$props.b + this.$data.c this.a this.b this.c diff --git a/packages/runtime-core/src/component.ts b/packages/runtime-core/src/component.ts index 5249cb09..d003d2f5 100644 --- a/packages/runtime-core/src/component.ts +++ b/packages/runtime-core/src/component.ts @@ -39,8 +39,7 @@ type SetupFunction = ( type RenderFunction = < Bindings extends UnwrapRef >( - this: ComponentRenderProxy, - ctx: ComponentRenderProxy + this: ComponentRenderProxy ) => VNodeChild interface ComponentOptionsWithoutProps { @@ -103,7 +102,6 @@ export const enum LifecycleHooks { interface SetupContext { attrs: Data slots: Slots - refs: Data emit: ((event: string, ...args: unknown[]) => void) } @@ -126,6 +124,7 @@ export type ComponentInstance

= { renderProxy: ComponentRenderProxy | null propsProxy: P | null setupContext: SetupContext | null + refs: Data // user namespace user: { [key: string]: any } @@ -280,15 +279,13 @@ export function setupStatefulComponent(instance: ComponentInstance) { const Component = instance.type as ComponentOptions // 1. create render proxy instance.renderProxy = new Proxy(instance, RenderProxyHandlers) as any - // 2. call setup() + // 2. create props proxy + // the propsProxy is a reactive AND readonly proxy to the actual props. + // it will be updated in resolveProps() on updates before render + const propsProxy = (instance.propsProxy = readonly(instance.props)) + // 3. call setup() const { setup } = Component if (setup) { - // the props proxy makes the props object passed to setup() reactive - // so props change can be tracked by watchers - // it will be updated in resolveProps() on updates before render - const propsProxy = (instance.propsProxy = setup.length - ? readonly(instance.props) - : null) const setupContext = (instance.setupContext = setup.length > 1 ? createSetupContext(instance) : null) @@ -373,11 +370,9 @@ export function renderComponentRoot(instance: ComponentInstance): VNode { type: Component, vnode, renderProxy, - setupContext, props, slots, attrs, - refs, emit } = instance @@ -386,11 +381,7 @@ export function renderComponentRoot(instance: ComponentInstance): VNode { try { if (vnode.shapeFlag & ShapeFlags.STATEFUL_COMPONENT) { result = normalizeVNode( - (instance.render as RenderFunction).call( - renderProxy, - props, - setupContext - ) + (instance.render as RenderFunction).call(renderProxy) ) } else { // functional @@ -400,7 +391,6 @@ export function renderComponentRoot(instance: ComponentInstance): VNode { ? render(props, { attrs, slots, - refs, emit }) : render(props, null as any) diff --git a/packages/runtime-core/src/componentProxy.ts b/packages/runtime-core/src/componentProxy.ts index 2d37da1f..c67244e9 100644 --- a/packages/runtime-core/src/componentProxy.ts +++ b/packages/runtime-core/src/componentProxy.ts @@ -2,17 +2,18 @@ import { ComponentInstance } from './component' export const RenderProxyHandlers = { get(target: ComponentInstance, key: string) { - const { data, props } = target + const { data, props, propsProxy } = target if (data.hasOwnProperty(key)) { return data[key] } else if (props.hasOwnProperty(key)) { - return props[key] + // return the value from propsProxy for ref unwrapping and readonly + return (propsProxy as any)[key] } else { switch (key) { case '$data': return data case '$props': - return props + return propsProxy case '$attrs': return target.attrs case '$slots':