Vue3核心Typescript类解析

与使用JavaScript不同的是,用Typescript写Vue程序要需要了解Vue的相关类型。Vue核心的类型,大部分写在@vue/runtime-core包中。

Component

Vue页面是由一个个组件组成的,组件在Vue中的类是Component,继承了ComponentOptionsFunctionalComponentComponentPublicInstanceConstructor

其中,ComponentOptions继承了ComponentOptionsBase,就是是我们经常写的声明式的包含datamethods等属性的选项组件:

FunctionalComponent是函数式组件,ComponentPublicInstanceConstructor是实例构造器(构造函数)。

ComponentOptions继承了ComponentCustomOptions,这个接口在Vue源码中是空的,我们可以借助它了自定义Vue组件选项中的属性,比如源码中的例子:

declare module '@vue/runtime-core' {
  interface ComponentCustomOptions {
    beforeRouteUpdate?(
      to: Route,
      from: Route,
      next: () => void
    ): void
  }
}

我们在定义组件时使用的defineComponent函数用于帮助我们进行组件选项的类型声明,它接受ComponentOptionsWithoutPropsComponentOptionsWithArrayPropsComponentOptionsWithObjectProps作为选项参数。它们都继承了ComponentOptionsBase,但具有不同的声明props的形式。这个函数也可以接受setup函数。

defineComponent函数返回DefineComponent类对象,它是ComponentOptionsBaseComponentPublicInstanceConstructor的交集类对象:

type DefineComponent = ComponentPublicInstanceConstructor & ComponentOptionsBase && 

CreateAppFunction

在V3中,一个页面的启动通常是从createApp开始的,它的类型声明是这样的:

export type CreateAppFunction<HostElement> = (
  rootComponent: Component,
  rootProps?: Data | null
) => App<HostElement>

它接受一个Component和属性作为参数,返回一个App

App

App实例是一个Vue的顶层对象,通过它可以设置共享属性、设置插件、注册组件、设置编译选项、设置错误处理函数等。

https://v3.cn.vuejs.org/api/application-api.html

通过mount方法可以将根组件挂载到文档中,并返回一个ComponentPublicInstance对象。

ComponentPublicInstance

ComponentPublicInstance是组件实例,包含$el,'emit‘‘emit‘‘props等属性。Vue以Component为模板,创建了ComponentPublicInstance`。

它的类型定义为:

type ComponentPublicInstance<
  P = {}, // props type extracted from props option
  B = {}, // raw bindings returned from setup()
  D = {}, // return from data()
  C extends ComputedOptions = {},
  M extends MethodOptions = {},
  E extends EmitsOptions = {},
  PublicProps = P,
  Defaults = {},
  MakeDefaultsOptional extends boolean = false,
  Options = ComponentOptionsBase<any, any, any, any, any, any, any, any, any>
> = {
  $: ComponentInternalInstance
  $data: D
  $props: MakeDefaultsOptional extends true
    ? Partial<Defaults> & Omit<P & PublicProps, keyof Defaults>
    : P & PublicProps
  $attrs: Data
  $refs: Data
  $slots: Slots
  $root: ComponentPublicInstance | null
  $parent: ComponentPublicInstance | null
  $emit: EmitFn<E>
  $el: any
  $options: Options & MergedComponentOptionsOverride
  $forceUpdate: () => void
  $nextTick: typeof nextTick
  $watch(
    source: string | Function,
    cb: Function,
    options?: WatchOptions
  ): WatchStopHandle
} & P &
  ShallowUnwrapRef<B> &
  UnwrapNestedRefs<D> &
  ExtractComputedReturns<C> &
  M &
  ComponentCustomProperties

其中$options就是我们在写组件时的ComponentOptionsBase类对象(如果有的话,对于函数式组件则包含一个renderer方法)和MergedComponentOptionsOverride(钩子函数)交集类。

PShallowUnwrapRefUnwrapNestedRefsExtractComputedReturnsM帮助我们可以用this[...]的方式读取组件实例的数据属性和方法。

ComponentCustomProperties在源码中是一个空接口,我们可以通过它来自定义组件实例上的属性。示例:

import { Router } from 'vue-router'

declare module '@vue/runtime-core' {
  interface ComponentCustomProperties {
    $router: Router
  }
}

$属性是ComponentInternalInstance类对象,表示组件的内部示例,包含了一些为高级应用提供的属性,包括VNode