]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
types: improve public component type
authorEvan You <yyx990803@gmail.com>
Sun, 14 Oct 2018 01:13:56 +0000 (21:13 -0400)
committerEvan You <yyx990803@gmail.com>
Sun, 14 Oct 2018 01:13:56 +0000 (21:13 -0400)
packages/core/src/component.ts
packages/core/src/componentOptions.ts
packages/core/src/componentUtils.ts
packages/core/src/h.ts
packages/core/src/index.ts
packages/core/src/vdom.ts

index 984693d1f47c41ab548f8bff53eadd991b456300..d08ce976891417917ab014d39e15e35f69474079 100644 (file)
@@ -1,4 +1,4 @@
-import { EMPTY_OBJ } from './utils'
+import { EMPTY_OBJ, NOOP } from './utils'
 import { VNode, Slots, RenderNode, MountedVNode } from './vdom'
 import {
   Data,
@@ -13,37 +13,43 @@ import { nextTick } from '@vue/scheduler'
 import { ErrorTypes } from './errorHandling'
 import { initializeComponentInstance } from './componentUtils'
 
-export interface ComponentClass extends ComponentClassOptions {
-  options?: ComponentOptions
-  new <P = {}, D = {}>(): MergedComponent<P, D>
+// public component instance type
+export interface Component<P = {}, D = {}> extends PublicInstanceMethods {
+  readonly $el: any
+  readonly $vnode: MountedVNode
+  readonly $parentVNode: MountedVNode
+  readonly $data: D
+  readonly $props: Readonly<P>
+  readonly $attrs: Readonly<Data>
+  readonly $slots: Slots
+  readonly $root: Component
+  readonly $parent: Component
+  readonly $children: Component[]
+  readonly $options: ComponentOptions<P, D, this>
+  readonly $refs: Record<string | symbol, any>
+  readonly $proxy: this
 }
 
-export type MergedComponent<P, D> = D & P & ComponentInstance<P, D>
-
-export interface FunctionalComponent<P = {}> {
-  (props: P, slots: Slots, attrs: Data): any
-  pure?: boolean
-  props?: ComponentPropsOptions<P>
-  displayName?: string
+interface PublicInstanceMethods {
+  $forceUpdate(): void
+  $nextTick(fn: () => any): Promise<void>
+  $watch(
+    keyOrFn: string | ((this: this) => any),
+    cb: (this: this, newValue: any, oldValue: any) => void,
+    options?: WatchOptions
+  ): () => void
+  $on(event: string, fn: Function): this
+  $once(event: string, fn: Function): this
+  $off(event?: string, fn?: Function): this
+  $emit(name: string, ...payload: any[]): this
 }
 
-export type ComponentType = ComponentClass | FunctionalComponent
-
-export interface ComponentInstance<P = {}, D = {}> extends InternalComponent {
-  constructor: ComponentClass
-
-  $vnode: MountedVNode
-  $data: D
-  $props: Readonly<P>
-  $attrs: Data
-  $slots: Slots
-  $root: ComponentInstance
-  $children: ComponentInstance[]
-
+interface APIMethods<P, D> {
   data?(): Partial<D>
   render(props: Readonly<P>, slots: Slots, attrs: Data): any
-  renderTracked?(e: DebuggerEvent): void
-  renderTriggered?(e: DebuggerEvent): void
+}
+
+interface LifecycleMethods {
   beforeCreate?(): void
   created?(): void
   beforeMount?(): void
@@ -60,50 +66,83 @@ export interface ComponentInstance<P = {}, D = {}> extends InternalComponent {
   ) => boolean | void
   activated?(): void
   deactivated?(): void
+  renderTracked?(e: DebuggerEvent): void
+  renderTriggered?(e: DebuggerEvent): void
+}
+
+export interface ComponentClass extends ComponentClassOptions {
+  options?: ComponentOptions
+  new <P = {}, D = {}>(): Component<P, D> & D & P
+}
+
+export interface FunctionalComponent<P = {}> {
+  (props: P, slots: Slots, attrs: Data): any
+  pure?: boolean
+  props?: ComponentPropsOptions<P>
+  displayName?: string
+}
+
+export type ComponentType = ComponentClass | FunctionalComponent
+
+// Internal type that represents a mounted instance.
+// It extends InternalComponent with mounted instance properties.
+export interface ComponentInstance<P = {}, D = {}>
+  extends InternalComponent,
+    APIMethods<P, D>,
+    LifecycleMethods {
+  constructor: ComponentClass
+
+  $vnode: MountedVNode
+  $data: D
+  $props: P
+  $attrs: Data
+  $slots: Slots
+  $root: ComponentInstance
+  $children: ComponentInstance[]
 
   _updateHandle: Autorun
   _queueJob: ((fn: () => void) => void)
-  $forceUpdate: () => void
-  $nextTick: (fn: () => void) => Promise<any>
-
   _self: ComponentInstance<D, P> // on proxies only
 }
 
-class InternalComponent {
-  public get $el(): RenderNode | null {
+// actual implementation of the component
+class InternalComponent implements PublicInstanceMethods {
+  get $el(): any {
     return this.$vnode && this.$vnode.el
   }
 
-  public $vnode: VNode | null = null
-  public $parentVNode: VNode | null = null
-  public $data: Data | null = null
-  public $props: Data | null = null
-  public $attrs: Data | null = null
-  public $slots: Slots | null = null
-  public $root: ComponentInstance | null = null
-  public $parent: ComponentInstance | null = null
-  public $children: ComponentInstance[] = []
-  public $options: ComponentOptions
-  public $refs: Record<string, ComponentInstance | RenderNode> = {}
-  public $proxy: any = null
-  public $forceUpdate: (() => void) | null = null
-
-  public _rawData: Data | null = null
-  public _computedGetters: Record<string, ComputedGetter> | null = null
-  public _watchHandles: Set<Autorun> | null = null
-  public _mounted: boolean = false
-  public _unmounted: boolean = false
-  public _events: { [event: string]: Function[] | null } | null = null
-  public _updateHandle: Autorun | null = null
-  public _queueJob: ((fn: () => void) => void) | null = null
-  public _isVue: boolean = true
-  public _inactiveRoot: boolean = false
+  $vnode: VNode | null = null
+  $parentVNode: VNode | null = null
+  $data: Data | null = null
+  $props: Data | null = null
+  $attrs: Data | null = null
+  $slots: Slots | null = null
+  $root: ComponentInstance | null = null
+  $parent: ComponentInstance | null = null
+  $children: ComponentInstance[] = []
+  $options: ComponentOptions
+  $refs: Record<string, ComponentInstance | RenderNode> = {}
+  $proxy: any = null
+
+  _rawData: Data | null = null
+  _computedGetters: Record<string, ComputedGetter> | null = null
+  _watchHandles: Set<Autorun> | null = null
+  _mounted: boolean = false
+  _unmounted: boolean = false
+  _events: { [event: string]: Function[] | null } | null = null
+  _updateHandle: Autorun | null = null
+  _queueJob: ((fn: () => void) => void) | null = null
+  _isVue: boolean = true
+  _inactiveRoot: boolean = false
 
   constructor() {
     initializeComponentInstance(this as any)
   }
 
-  $nextTick(fn: () => any): Promise<any> {
+  // to be set by renderer during mount
+  $forceUpdate: () => void = NOOP
+
+  $nextTick(fn: () => any): Promise<void> {
     return nextTick(fn)
   }
 
index 08cf83c86e61bc999afdc8421a43cba4b31f4bad..bd436fb96b6025b1f53a2623f2db0ec90989810b 100644 (file)
@@ -1,4 +1,4 @@
-import { ComponentInstance, MergedComponent } from './component'
+import { ComponentInstance, Component } from './component'
 import { Slots } from './vdom'
 
 export type Data = Record<string, any>
@@ -10,7 +10,7 @@ export interface ComponentClassOptions<P = {}, This = ComponentInstance> {
   displayName?: string
 }
 
-export interface ComponentOptions<P = {}, D = {}, This = MergedComponent<P, D>>
+export interface ComponentOptions<P = {}, D = {}, This = Component<P, D>>
   extends ComponentClassOptions<P, This> {
   data?(): D
   render?: (this: This, props: Readonly<Data>, slots: Slots, attrs: Data) => any
index 2950f67c555f23080d352f3e352ac823e2f669ee..04a8808b5d854b81b9b92ef7f05bd459c5767d6d 100644 (file)
@@ -39,7 +39,7 @@ export function createComponentInstance(
   // always pass args in super()
   currentVNode = vnode
   currentContextVNode = contextVNode
-  const instance = (vnode.children = new Component()) as ComponentInstance
+  const instance = (vnode.children = new Component() as ComponentInstance)
   // then we finish the initialization by collecting properties set on the
   // instance
   initializeState(instance)
index c07e11f484f259d328f83aede575ce02e6d5e726..9d4bcb977d59f1696794ff6cbd9f4a3ca56d7282 100644 (file)
@@ -1,9 +1,5 @@
 import { ChildrenFlags } from './flags'
-import {
-  ComponentClass,
-  FunctionalComponent,
-  ComponentInstance
-} from './component'
+import { ComponentClass, FunctionalComponent, Component } from './component'
 import { ComponentOptions } from './componentOptions'
 import {
   VNode,
@@ -93,9 +89,9 @@ interface createElement extends VNodeFactories {
     children?: RawChildrenType | RawSlots
   ): VNode
   // class
-  <P>(tag: new () => ComponentInstance<P>, children?: RawChildrenType): VNode
+  <P>(tag: new () => Component<P>, children?: RawChildrenType): VNode
   <P>(
-    tag: new () => ComponentInstance<P>,
+    tag: new () => Component<P>,
     data?: (P & BuiltInProps & Differ) | null,
     children?: RawChildrenType | RawSlots
   ): VNode
index 2feec952176302501b8aa57ee9b5fd4c130068ba..6c2d323c39974763823fcd949515d5ddf6a6fb0c 100644 (file)
@@ -24,12 +24,7 @@ export { createAsyncComponent } from './optional/asyncComponent'
 export { KeepAlive } from './optional/keepAlive'
 
 // flags & types
-export {
-  ComponentType,
-  ComponentClass,
-  FunctionalComponent,
-  ComponentInstance
-} from './component'
+export { ComponentType, ComponentClass, FunctionalComponent } from './component'
 export * from './componentOptions'
 export { VNodeFlags, ChildrenFlags } from './flags'
 export { VNode, Slots } from './vdom'
index 811f7b26080fa1cc8785cff1d34ace07339da49a..3db116df09e43b8e6330a046f892ad78dfccc1ba 100644 (file)
@@ -56,6 +56,7 @@ export type VNodeChildren =
   | ComponentInstance // COMPONENT_STATEFUL
   | VNode // COMPONENT_FUNCTIONAL
   | string // TEXT
+  | null
 
 export type Key = string | number