]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor: reorganize component related code and types
authorEvan You <yyx990803@gmail.com>
Fri, 6 Sep 2019 15:19:22 +0000 (11:19 -0400)
committerEvan You <yyx990803@gmail.com>
Fri, 6 Sep 2019 15:19:22 +0000 (11:19 -0400)
packages/runtime-core/__tests__/apiCreateComponent.spec.tsx
packages/runtime-core/src/apiApp.ts
packages/runtime-core/src/apiCreateComponent.ts [new file with mode: 0644]
packages/runtime-core/src/apiLifecycle.ts
packages/runtime-core/src/component.ts
packages/runtime-core/src/componentOptions.ts [moved from packages/runtime-core/src/apiOptions.ts with 74% similarity]
packages/runtime-core/src/componentProxy.ts
packages/runtime-core/src/directives.ts
packages/runtime-core/src/h.ts
packages/runtime-core/src/index.ts

index f1ebdf54336d1302710d430bc2b1cf4212e84582..978cd32a06e513b5357367d4d8f48e82479bb142 100644 (file)
@@ -1,4 +1,4 @@
-import { createComponent } from '../src/component'
+import { createComponent } from '../src/apiCreateComponent'
 import { ref } from '@vue/reactivity'
 import { PropType } from '../src/componentProps'
 import { h } from '../src/h'
index cd410c4eb9e72dec302163f7bf535891b3b95864..94a05bb410b4c4485229dd02e8176339e940b6f1 100644 (file)
@@ -1,10 +1,6 @@
-import {
-  ComponentOptions,
-  Component,
-  ComponentRenderProxy,
-  Data,
-  ComponentInstance
-} from './component'
+import { Component, Data, ComponentInstance } from './component'
+import { ComponentOptions } from './componentOptions'
+import { ComponentRenderProxy } from './componentProxy'
 import { Directive } from './directives'
 import { HostNode, RootRenderFunction } from './createRenderer'
 import { InjectionKey } from './apiInject'
diff --git a/packages/runtime-core/src/apiCreateComponent.ts b/packages/runtime-core/src/apiCreateComponent.ts
new file mode 100644 (file)
index 0000000..098452e
--- /dev/null
@@ -0,0 +1,81 @@
+import {
+  ComputedOptions,
+  MethodOptions,
+  ComponentOptionsWithoutProps,
+  ComponentOptionsWithArrayProps,
+  ComponentOptionsWithProps
+} from './componentOptions'
+import { SetupContext } from './component'
+import { VNodeChild } from './vnode'
+import { ComponentRenderProxy } from './componentProxy'
+import { ExtractPropTypes } from './componentProps'
+import { isFunction } from '@vue/shared'
+
+// overload 1: direct setup function
+// (uses user defined props interface)
+export function createComponent<Props>(
+  setup: (props: Props, ctx: SetupContext) => object | (() => VNodeChild)
+): (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,
+  D,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {}
+>(
+  options: ComponentOptionsWithoutProps<Props, RawBindings, D, C, M>
+): {
+  new (): ComponentRenderProxy<Props, RawBindings, D, C, M>
+}
+
+// overload 3: object format with array props declaration
+// props inferred as { [key in PropNames]?: unknown }
+// return type is for Vetur and TSX support
+export function createComponent<
+  PropNames extends string,
+  RawBindings,
+  D,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {}
+>(
+  options: ComponentOptionsWithArrayProps<PropNames, RawBindings, D, C, M>
+): {
+  new (): ComponentRenderProxy<
+    { [key in PropNames]?: unknown },
+    RawBindings,
+    D,
+    C,
+    M
+  >
+}
+
+// overload 4: object format with object props declaration
+// see `ExtractPropTypes` in ./componentProps.ts
+export function createComponent<
+  PropsOptions,
+  RawBindings,
+  D,
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {}
+>(
+  options: ComponentOptionsWithProps<PropsOptions, RawBindings, D, C, M>
+): {
+  // for Vetur and TSX support
+  new (): ComponentRenderProxy<
+    ExtractPropTypes<PropsOptions>,
+    RawBindings,
+    D,
+    C,
+    M,
+    ExtractPropTypes<PropsOptions, false>
+  >
+}
+
+// implementation, close to no-op
+export function createComponent(options: any) {
+  return isFunction(options) ? { setup: options } : (options as any)
+}
index a9f0918094c25981870df14e875f009e04335ada..d2644b6362070c8a258d4c7539c81dfcf3865167 100644 (file)
@@ -2,9 +2,9 @@ import {
   ComponentInstance,
   LifecycleHooks,
   currentInstance,
-  setCurrentInstance,
-  ComponentRenderProxy
+  setCurrentInstance
 } from './component'
+import { ComponentRenderProxy } from './componentProxy'
 import { callWithAsyncErrorHandling, ErrorTypeStrings } from './errorHandling'
 import { warn } from './warning'
 import { capitalize } from '@vue/shared'
index 3583d70f5834d7e1a959e83f2234c47d0008661b..a954efadc3527c6f63d3de2556656a55963d3668 100644 (file)
@@ -1,15 +1,7 @@
 import { VNode, normalizeVNode, VNodeChild, createVNode, Empty } from './vnode'
-import { ReactiveEffect, UnwrapRef, reactive, readonly } from '@vue/reactivity'
-import {
-  EMPTY_OBJ,
-  isFunction,
-  capitalize,
-  NOOP,
-  isArray,
-  isObject
-} from '@vue/shared'
-import { RenderProxyHandlers } from './componentProxy'
-import { ComponentPropsOptions, ExtractPropTypes } from './componentProps'
+import { ReactiveEffect, reactive, readonly } from '@vue/reactivity'
+import { RenderProxyHandlers, ComponentRenderProxy } from './componentProxy'
+import { ComponentPropsOptions } from './componentProps'
 import { Slots } from './componentSlots'
 import { PatchFlags } from './patchFlags'
 import { ShapeFlags } from './shapeFlags'
@@ -24,100 +16,20 @@ import { AppContext, createAppContext } from './apiApp'
 import { Directive } from './directives'
 import {
   applyOptions,
-  LegacyOptions,
   resolveAsset,
-  ComputedOptions,
-  MethodOptions,
-  ExtracComputedReturns
-} from './apiOptions'
+  ComponentOptions
+} from './componentOptions'
+import {
+  EMPTY_OBJ,
+  isFunction,
+  capitalize,
+  NOOP,
+  isArray,
+  isObject
+} from '@vue/shared'
 
 export type Data = { [key: string]: unknown }
 
-// 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 = {},
-  B = {},
-  D = {},
-  C = {},
-  M = {},
-  PublicProps = P
-> = {
-  $data: D
-  $props: PublicProps
-  $attrs: Data
-  $refs: Data
-  $slots: Data
-  $root: ComponentInstance | null
-  $parent: ComponentInstance | null
-  $emit: (event: string, ...args: unknown[]) => void
-} & P &
-  UnwrapRef<B> &
-  D &
-  ExtracComputedReturns<C> &
-  M
-
-interface ComponentOptionsBase<
-  Props,
-  RawBindings,
-  D,
-  C extends ComputedOptions,
-  M extends MethodOptions
-> extends LegacyOptions<Props, RawBindings, D, C, M> {
-  setup?: (
-    this: null,
-    props: Props,
-    ctx: SetupContext
-  ) => RawBindings | (() => VNodeChild) | void
-  name?: string
-  template?: string
-  // Note: we are intentionally using the signature-less `Function` type here
-  // since any type with signature will cause the whole inference to fail when
-  // the return expression contains reference to `this`.
-  // Luckily `render()` doesn't need any arguments nor does it care about return
-  // type.
-  render?: Function
-  components?: Record<string, Component>
-  directives?: Record<string, Directive>
-}
-
-export type ComponentOptionsWithoutProps<
-  Props = {},
-  RawBindings = {},
-  D = {},
-  C extends ComputedOptions = {},
-  M extends MethodOptions = {}
-> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
-  props?: undefined
-} & ThisType<ComponentRenderProxy<Props, RawBindings, D, C, M>>
-
-export type ComponentOptionsWithArrayProps<
-  PropNames extends string = string,
-  RawBindings = {},
-  D = {},
-  C extends ComputedOptions = {},
-  M extends MethodOptions = {},
-  Props = { [key in PropNames]?: unknown }
-> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
-  props: PropNames[]
-} & ThisType<ComponentRenderProxy<Props, RawBindings, D, C, M>>
-
-export type ComponentOptionsWithProps<
-  PropsOptions = ComponentPropsOptions,
-  RawBindings = {},
-  D = {},
-  C extends ComputedOptions = {},
-  M extends MethodOptions = {},
-  Props = ExtractPropTypes<PropsOptions>
-> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
-  props: PropsOptions
-} & ThisType<ComponentRenderProxy<Props, RawBindings, D, C, M>>
-
-export type ComponentOptions =
-  | ComponentOptionsWithoutProps
-  | ComponentOptionsWithProps
-  | ComponentOptionsWithArrayProps
-
 export interface FunctionalComponent<P = {}> {
   (props: P, ctx: SetupContext): VNodeChild
   props?: ComponentPropsOptions<P>
@@ -146,7 +58,7 @@ export const enum LifecycleHooks {
 
 type Emit = ((event: string, ...args: unknown[]) => void)
 
-interface SetupContext {
+export interface SetupContext {
   attrs: Data
   slots: Slots
   emit: Emit
@@ -201,72 +113,6 @@ export interface ComponentInstance {
   [LifecycleHooks.ERROR_CAPTURED]: LifecycleHook
 }
 
-// createComponent
-// overload 1: direct setup function
-// (uses user defined props interface)
-export function createComponent<Props>(
-  setup: (props: Props, ctx: SetupContext) => object | (() => VNodeChild)
-): (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,
-  D,
-  C extends ComputedOptions = {},
-  M extends MethodOptions = {}
->(
-  options: ComponentOptionsWithoutProps<Props, RawBindings, D, C, M>
-): {
-  new (): ComponentRenderProxy<Props, RawBindings, D, C, M>
-}
-// overload 3: object format with array props declaration
-// props inferred as { [key in PropNames]?: unknown }
-// return type is for Vetur and TSX support
-export function createComponent<
-  PropNames extends string,
-  RawBindings,
-  D,
-  C extends ComputedOptions = {},
-  M extends MethodOptions = {}
->(
-  options: ComponentOptionsWithArrayProps<PropNames, RawBindings, D, C, M>
-): {
-  new (): ComponentRenderProxy<
-    { [key in PropNames]?: unknown },
-    RawBindings,
-    D,
-    C,
-    M
-  >
-}
-// overload 4: object format with object props declaration
-// see `ExtractPropTypes` in ./componentProps.ts
-export function createComponent<
-  PropsOptions,
-  RawBindings,
-  D,
-  C extends ComputedOptions = {},
-  M extends MethodOptions = {}
->(
-  options: ComponentOptionsWithProps<PropsOptions, RawBindings, D, C, M>
-): {
-  // for Vetur and TSX support
-  new (): ComponentRenderProxy<
-    ExtractPropTypes<PropsOptions>,
-    RawBindings,
-    D,
-    C,
-    M,
-    ExtractPropTypes<PropsOptions, false>
-  >
-}
-// implementation, close to no-op
-export function createComponent(options: any) {
-  return isFunction(options) ? { setup: options } : (options as any)
-}
-
 const emptyAppContext = createAppContext()
 
 export function createComponentInstance(
similarity index 74%
rename from packages/runtime-core/src/apiOptions.ts
rename to packages/runtime-core/src/componentOptions.ts
index 3863d64c42e541b0969c2ee1644d6d176a8e93fa..85cdb26cc12612e20559684c2fb91f467f568de6 100644 (file)
@@ -1,10 +1,10 @@
 import {
   ComponentInstance,
   Data,
-  ComponentOptions,
   currentRenderingInstance,
   currentInstance,
-  ComponentRenderProxy
+  Component,
+  SetupContext
 } from './component'
 import {
   isFunction,
@@ -31,6 +31,71 @@ import {
 } from './apiLifecycle'
 import { DebuggerEvent, reactive } from '@vue/reactivity'
 import { warn } from './warning'
+import { ComponentPropsOptions, ExtractPropTypes } from './componentProps'
+import { Directive } from './directives'
+import { VNodeChild } from './vnode'
+import { ComponentRenderProxy } from './componentProxy'
+
+interface ComponentOptionsBase<
+  Props,
+  RawBindings,
+  D,
+  C extends ComputedOptions,
+  M extends MethodOptions
+> extends LegacyOptions<Props, RawBindings, D, C, M> {
+  setup?: (
+    this: null,
+    props: Props,
+    ctx: SetupContext
+  ) => RawBindings | (() => VNodeChild) | void
+  name?: string
+  template?: string
+  // Note: we are intentionally using the signature-less `Function` type here
+  // since any type with signature will cause the whole inference to fail when
+  // the return expression contains reference to `this`.
+  // Luckily `render()` doesn't need any arguments nor does it care about return
+  // type.
+  render?: Function
+  components?: Record<string, Component>
+  directives?: Record<string, Directive>
+}
+
+export type ComponentOptionsWithoutProps<
+  Props = {},
+  RawBindings = {},
+  D = {},
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {}
+> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
+  props?: undefined
+} & ThisType<ComponentRenderProxy<Props, RawBindings, D, C, M>>
+
+export type ComponentOptionsWithArrayProps<
+  PropNames extends string = string,
+  RawBindings = {},
+  D = {},
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Props = { [key in PropNames]?: unknown }
+> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
+  props: PropNames[]
+} & ThisType<ComponentRenderProxy<Props, RawBindings, D, C, M>>
+
+export type ComponentOptionsWithProps<
+  PropsOptions = ComponentPropsOptions,
+  RawBindings = {},
+  D = {},
+  C extends ComputedOptions = {},
+  M extends MethodOptions = {},
+  Props = ExtractPropTypes<PropsOptions>
+> = ComponentOptionsBase<Props, RawBindings, D, C, M> & {
+  props: PropsOptions
+} & ThisType<ComponentRenderProxy<Props, RawBindings, D, C, M>>
+
+export type ComponentOptions =
+  | ComponentOptionsWithoutProps
+  | ComponentOptionsWithProps
+  | ComponentOptionsWithArrayProps
 
 // TODO legacy component definition also supports constructors with .options
 type LegacyComponent = ComponentOptions
@@ -60,6 +125,18 @@ type WatchHandler = (
   onCleanup: CleanupRegistrator
 ) => void
 
+type ComponentWatchOptions = Record<
+  string,
+  string | WatchHandler | { handler: WatchHandler } & WatchOptions
+>
+
+type ComponentInjectOptions =
+  | string[]
+  | Record<
+      string | symbol,
+      string | symbol | { from: string | symbol; default?: any }
+    >
+
 // TODO type inference for these options
 export interface LegacyOptions<
   Props,
@@ -71,21 +148,16 @@ export interface LegacyOptions<
   el?: any
 
   // state
+  // Limitation: we cannot expose RawBindings on the `this` context for data
+  // since that leads to some sort of circular inference and breaks ThisType
+  // for the entire component.
   data?: D | ((this: ComponentRenderProxy<Props>) => D)
   computed?: C
   methods?: M
   // TODO watch array
-  watch?: Record<
-    string,
-    string | WatchHandler | { handler: WatchHandler } & WatchOptions
-  >
+  watch?: ComponentWatchOptions
   provide?: Data | Function
-  inject?:
-    | string[]
-    | Record<
-        string | symbol,
-        string | symbol | { from: string | symbol; default?: any }
-      >
+  inject?: ComponentInjectOptions
 
   // composition
   mixins?: LegacyComponent[]
index 716df5779554f17ace29f6c6d616dd64a683efe8..b9580623160c430840105e687193df25b4b1af14 100644 (file)
@@ -1,7 +1,33 @@
-import { ComponentInstance } from './component'
+import { ComponentInstance, Data } from './component'
 import { nextTick } from './scheduler'
 import { instanceWatch } from './apiWatch'
 import { EMPTY_OBJ, hasOwn } from '@vue/shared'
+import { ExtracComputedReturns } from './componentOptions'
+import { UnwrapRef } from '@vue/reactivity'
+
+// 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 = {},
+  B = {},
+  D = {},
+  C = {},
+  M = {},
+  PublicProps = P
+> = {
+  $data: D
+  $props: PublicProps
+  $attrs: Data
+  $refs: Data
+  $slots: Data
+  $root: ComponentInstance | null
+  $parent: ComponentInstance | null
+  $emit: (event: string, ...args: unknown[]) => void
+} & P &
+  UnwrapRef<B> &
+  D &
+  ExtracComputedReturns<C> &
+  M
 
 export const RenderProxyHandlers = {
   get(target: ComponentInstance, key: string) {
index d18afeace50e4f8a50cfb1db3a0dc756486c1374..dd3f542a6408af827ef308afb6990a9f08a87fe0 100644 (file)
@@ -14,14 +14,11 @@ return applyDirectives(h(comp), [
 import { VNode, cloneVNode } from './vnode'
 import { extend, isArray, isFunction } from '@vue/shared'
 import { warn } from './warning'
-import {
-  ComponentInstance,
-  currentRenderingInstance,
-  ComponentRenderProxy
-} from './component'
+import { ComponentInstance, currentRenderingInstance } from './component'
 import { callWithAsyncErrorHandling, ErrorTypes } from './errorHandling'
 import { HostNode } from './createRenderer'
-import { resolveAsset } from './apiOptions'
+import { resolveAsset } from './componentOptions'
+import { ComponentRenderProxy } from './componentProxy'
 
 export interface DirectiveBinding {
   instance: ComponentRenderProxy | null
index ca94b7c73b7c8c3a2e83c6c8cb160065bd0b0053..5ebb485d920f05098bac457d28a917dcb28c0080 100644 (file)
@@ -9,13 +9,13 @@ import {
 import { isObject, isArray } from '@vue/shared'
 import { Ref } from '@vue/reactivity'
 import { RawSlots } from './componentSlots'
+import { FunctionalComponent } from './component'
 import {
-  FunctionalComponent,
   ComponentOptionsWithoutProps,
   ComponentOptionsWithArrayProps,
   ComponentOptionsWithProps,
   ComponentOptions
-} from './component'
+} from './componentOptions'
 import { ExtractPropTypes } from './componentProps'
 
 // `h` is a more user-friendly version of `createVNode` that allows omitting the
index 59fc13bca3a8b93a8e856c81d50762521fa73c5f..5b794cf39da2c695f6b25bb1e06dc9e14c6b8102 100644 (file)
@@ -1,6 +1,6 @@
 // Public API ------------------------------------------------------------------
 
-export { createComponent } from './component'
+export { createComponent } from './apiCreateComponent'
 export { nextTick } from './scheduler'
 export * from './apiReactivity'
 export * from './apiWatch'