// public properties exposed on the proxy, which is used as the render context
// in templates (as `this` in the render option)
export type ComponentRenderProxy<P = {}, S = {}, PublicProps = P> = {
- $state: S
+ $data: S
$props: PublicProps
$attrs: Data
$refs: Data
attrs: Data
slots: Slots
refs: Data
+ parent: ComponentInstance | null
+ root: ComponentInstance
emit: ((event: string, ...args: any[]) => void)
}
render: RenderFunction<P, S> | null
// the rest are only for stateful components
- state: S
+ data: S
props: P
renderProxy: ComponentRenderProxy | null
propsProxy: P | null
effects: null,
// public properties
- state: EMPTY_OBJ,
+ data: EMPTY_OBJ,
props: EMPTY_OBJ,
attrs: EMPTY_OBJ,
slots: EMPTY_OBJ,
export function setupStatefulComponent(instance: ComponentInstance) {
const Component = instance.type as ComponentOptions
// 1. create render proxy
- const proxy = (instance.renderProxy = new Proxy(
- instance,
- RenderProxyHandlers
- ) as any)
+ instance.renderProxy = new Proxy(instance, RenderProxyHandlers) as any
// 2. call setup()
const { setup } = Component
if (setup) {
: null)
const setupContext = (instance.setupContext =
setup.length > 1 ? createSetupContext(instance) : null)
- const setupResult = setup.call(proxy, propsProxy, setupContext)
+ const setupResult = setup.call(null, propsProxy, setupContext)
if (isFunction(setupResult)) {
// setup returned an inline render function
instance.render = setupResult
} else {
// setup returned bindings.
// assuming a render function compiled from template is present.
- instance.state = state(setupResult)
+ instance.data = state(setupResult)
if (__DEV__ && !Component.render) {
// TODO warn missing render fn
}
attrs: new Proxy(instance, SetupProxyHandlers.attrs),
slots: new Proxy(instance, SetupProxyHandlers.slots),
refs: new Proxy(instance, SetupProxyHandlers.refs),
- emit: instance.emit
+ emit: instance.emit,
+ parent: instance.parent,
+ root: instance.root
} as any
return __DEV__ ? Object.freeze(context) : context
}
slots,
attrs,
refs,
- emit
+ emit,
+ parent,
+ root
} = instance
if (vnode.shapeFlag & STATEFUL_COMPONENT) {
return normalizeVNode(
)
} else {
// functional
+ const render = Component as FunctionalComponent
return normalizeVNode(
- (Component as FunctionalComponent)(props, {
- attrs,
- slots,
- refs,
- emit
- })
+ render.length > 1
+ ? render(props, {
+ attrs,
+ slots,
+ refs,
+ emit,
+ parent,
+ root
+ })
+ : render(props, null as any)
)
}
}
export const RenderProxyHandlers = {
get(target: ComponentInstance, key: string) {
- const { state, props } = target
- if (state.hasOwnProperty(key)) {
- return state[key]
+ const { data, props } = target
+ if (data.hasOwnProperty(key)) {
+ return data[key]
} else if (props.hasOwnProperty(key)) {
return props[key]
} else {
switch (key) {
- case '$state':
- return target.state
+ case '$data':
+ return data
case '$props':
- return target.props
+ return props
case '$attrs':
return target.attrs
case '$slots':
return target.parent
case '$root':
return target.root
- case '$el':
- return target.vnode && target.vnode.el
case '$emit':
return target.emit
default:
}
},
set(target: ComponentInstance, key: string, value: any): boolean {
- const { state } = target
- if (state.hasOwnProperty(key)) {
- state[key] = value
+ const { data } = target
+ if (data.hasOwnProperty(key)) {
+ data[key] = value
return true
} else {
if (__DEV__) {