|
@@ -14,15 +14,14 @@ import { STATEFUL_COMPONENT } from './typeFlags'
|
|
|
|
|
|
|
|
export type Data = { [key: string]: any }
|
|
export type Data = { [key: string]: any }
|
|
|
|
|
|
|
|
|
|
+// 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> = {
|
|
export type ComponentRenderProxy<P = {}, S = {}, PublicProps = P> = {
|
|
|
$state: S
|
|
$state: S
|
|
|
$props: PublicProps
|
|
$props: PublicProps
|
|
|
$attrs: Data
|
|
$attrs: Data
|
|
|
-
|
|
|
|
|
- // TODO
|
|
|
|
|
$refs: Data
|
|
$refs: Data
|
|
|
$slots: Data
|
|
$slots: Data
|
|
|
-
|
|
|
|
|
$root: ComponentInstance | null
|
|
$root: ComponentInstance | null
|
|
|
$parent: ComponentInstance | null
|
|
$parent: ComponentInstance | null
|
|
|
} & P &
|
|
} & P &
|
|
@@ -45,12 +44,8 @@ type RenderFunctionWithThis<Props, RawBindings> = <
|
|
|
vnode: VNode
|
|
vnode: VNode
|
|
|
) => VNodeChild
|
|
) => VNodeChild
|
|
|
|
|
|
|
|
-interface ComponentOptionsWithProps<
|
|
|
|
|
- PropsOptions = ComponentPropsOptions,
|
|
|
|
|
- RawBindings = Data,
|
|
|
|
|
- Props = ExtractPropTypes<PropsOptions>
|
|
|
|
|
-> {
|
|
|
|
|
- props: PropsOptions
|
|
|
|
|
|
|
+interface ComponentOptionsWithoutProps<Props = Data, RawBindings = Data> {
|
|
|
|
|
+ props?: undefined
|
|
|
setup?: (
|
|
setup?: (
|
|
|
this: ComponentRenderProxy<Props>,
|
|
this: ComponentRenderProxy<Props>,
|
|
|
props: Props
|
|
props: Props
|
|
@@ -58,8 +53,12 @@ interface ComponentOptionsWithProps<
|
|
|
render?: RenderFunctionWithThis<Props, RawBindings>
|
|
render?: RenderFunctionWithThis<Props, RawBindings>
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-interface ComponentOptionsWithoutProps<Props = Data, RawBindings = Data> {
|
|
|
|
|
- props?: undefined
|
|
|
|
|
|
|
+interface ComponentOptionsWithArrayProps<
|
|
|
|
|
+ PropNames extends string = string,
|
|
|
|
|
+ RawBindings = Data,
|
|
|
|
|
+ Props = { [key in PropNames]?: any }
|
|
|
|
|
+> {
|
|
|
|
|
+ props: PropNames[]
|
|
|
setup?: (
|
|
setup?: (
|
|
|
this: ComponentRenderProxy<Props>,
|
|
this: ComponentRenderProxy<Props>,
|
|
|
props: Props
|
|
props: Props
|
|
@@ -67,12 +66,12 @@ interface ComponentOptionsWithoutProps<Props = Data, RawBindings = Data> {
|
|
|
render?: RenderFunctionWithThis<Props, RawBindings>
|
|
render?: RenderFunctionWithThis<Props, RawBindings>
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-interface ComponentOptionsWithArrayProps<
|
|
|
|
|
- PropNames extends string = string,
|
|
|
|
|
|
|
+interface ComponentOptionsWithProps<
|
|
|
|
|
+ PropsOptions = ComponentPropsOptions,
|
|
|
RawBindings = Data,
|
|
RawBindings = Data,
|
|
|
- Props = { [key in PropNames]?: any }
|
|
|
|
|
|
|
+ Props = ExtractPropTypes<PropsOptions>
|
|
|
> {
|
|
> {
|
|
|
- props: PropNames[]
|
|
|
|
|
|
|
+ props: PropsOptions
|
|
|
setup?: (
|
|
setup?: (
|
|
|
this: ComponentRenderProxy<Props>,
|
|
this: ComponentRenderProxy<Props>,
|
|
|
props: Props
|
|
props: Props
|
|
@@ -80,7 +79,7 @@ interface ComponentOptionsWithArrayProps<
|
|
|
render?: RenderFunctionWithThis<Props, RawBindings>
|
|
render?: RenderFunctionWithThis<Props, RawBindings>
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type ComponentOptions =
|
|
|
|
|
|
|
+export type ComponentOptions =
|
|
|
| ComponentOptionsWithProps
|
|
| ComponentOptionsWithProps
|
|
|
| ComponentOptionsWithoutProps
|
|
| ComponentOptionsWithoutProps
|
|
|
| ComponentOptionsWithArrayProps
|
|
| ComponentOptionsWithArrayProps
|
|
@@ -126,25 +125,33 @@ export type ComponentInstance<P = Data, S = Data> = {
|
|
|
refs: Data
|
|
refs: Data
|
|
|
} & LifecycleHooks
|
|
} & LifecycleHooks
|
|
|
|
|
|
|
|
-// no-op, for type inference only
|
|
|
|
|
|
|
+// createComponent
|
|
|
|
|
+// overload 1: direct setup function
|
|
|
|
|
+// (uses user defined props interface)
|
|
|
export function createComponent<Props>(
|
|
export function createComponent<Props>(
|
|
|
setup: (props: Props) => RenderFunction<Props>
|
|
setup: (props: Props) => RenderFunction<Props>
|
|
|
): (props: Props) => any
|
|
): (props: Props) => any
|
|
|
|
|
+// overload 2: object format with no props
|
|
|
|
|
+// (uses user defined props interface)
|
|
|
|
|
+// return type is for Vetur and TSX support
|
|
|
|
|
+export function createComponent<Props, RawBindings>(
|
|
|
|
|
+ options: ComponentOptionsWithoutProps<Props, RawBindings>
|
|
|
|
|
+): {
|
|
|
|
|
+ new (): ComponentRenderProxy<Props, UnwrapValue<RawBindings>>
|
|
|
|
|
+}
|
|
|
|
|
+// overload 3: object format with array props declaration
|
|
|
|
|
+// props inferred as { [key in PropNames]?: any }
|
|
|
|
|
+// return type is for Vetur and TSX support
|
|
|
export function createComponent<PropNames extends string, RawBindings>(
|
|
export function createComponent<PropNames extends string, RawBindings>(
|
|
|
options: ComponentOptionsWithArrayProps<PropNames, RawBindings>
|
|
options: ComponentOptionsWithArrayProps<PropNames, RawBindings>
|
|
|
): {
|
|
): {
|
|
|
- // for Vetur and TSX support
|
|
|
|
|
new (): ComponentRenderProxy<
|
|
new (): ComponentRenderProxy<
|
|
|
{ [key in PropNames]?: any },
|
|
{ [key in PropNames]?: any },
|
|
|
UnwrapValue<RawBindings>
|
|
UnwrapValue<RawBindings>
|
|
|
>
|
|
>
|
|
|
}
|
|
}
|
|
|
-export function createComponent<Props, RawBindings>(
|
|
|
|
|
- options: ComponentOptionsWithoutProps<Props, RawBindings>
|
|
|
|
|
-): {
|
|
|
|
|
- // for Vetur and TSX support
|
|
|
|
|
- new (): ComponentRenderProxy<Props, UnwrapValue<RawBindings>>
|
|
|
|
|
-}
|
|
|
|
|
|
|
+// overload 4: object format with object props declaration
|
|
|
|
|
+// see `ExtractPropTypes` in ./componentProps.ts
|
|
|
export function createComponent<PropsOptions, RawBindings>(
|
|
export function createComponent<PropsOptions, RawBindings>(
|
|
|
options: ComponentOptionsWithProps<PropsOptions, RawBindings>
|
|
options: ComponentOptionsWithProps<PropsOptions, RawBindings>
|
|
|
): {
|
|
): {
|
|
@@ -155,6 +162,7 @@ export function createComponent<PropsOptions, RawBindings>(
|
|
|
ExtractPropTypes<PropsOptions, false>
|
|
ExtractPropTypes<PropsOptions, false>
|
|
|
>
|
|
>
|
|
|
}
|
|
}
|
|
|
|
|
+// implementation, close to no-op
|
|
|
export function createComponent(options: any) {
|
|
export function createComponent(options: any) {
|
|
|
return isFunction(options) ? { setup: options } : (options as any)
|
|
return isFunction(options) ? { setup: options } : (options as any)
|
|
|
}
|
|
}
|
|
@@ -222,10 +230,11 @@ export function setupStatefulComponent(instance: ComponentInstance) {
|
|
|
: null)
|
|
: null)
|
|
|
const setupResult = setup.call(proxy, propsProxy)
|
|
const setupResult = setup.call(proxy, propsProxy)
|
|
|
if (isFunction(setupResult)) {
|
|
if (isFunction(setupResult)) {
|
|
|
- // setup returned a render function
|
|
|
|
|
|
|
+ // setup returned an inline render function
|
|
|
instance.render = setupResult
|
|
instance.render = setupResult
|
|
|
} else {
|
|
} else {
|
|
|
- // setup returned bindings
|
|
|
|
|
|
|
+ // setup returned bindings.
|
|
|
|
|
+ // assuming a render function compiled from template is present.
|
|
|
instance.state = state(setupResult)
|
|
instance.state = state(setupResult)
|
|
|
if (__DEV__ && !Component.render) {
|
|
if (__DEV__ && !Component.render) {
|
|
|
// TODO warn missing render fn
|
|
// TODO warn missing render fn
|