跳到主要内容

官方实现

2023年06月11日
柏拉文
越努力,越幸运

一、src/core/index.ts


import Vue from './instance/index'
import { initGlobalAPI } from './global-api/index'
import { isServerRendering } from 'core/util/env'
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'
import { version } from 'v3'

initGlobalAPI(Vue)

Object.defineProperty(Vue.prototype, '$isServer', {
get: isServerRendering
})

Object.defineProperty(Vue.prototype, '$ssrContext', {
get() {
/* istanbul ignore next */
return this.$vnode && this.$vnode.ssrContext
}
})

// expose FunctionalRenderContext for ssr runtime helper installation
Object.defineProperty(Vue, 'FunctionalRenderContext', {
value: FunctionalRenderContext
})

Vue.version = version

export default Vue

二、src/core/global-api/index.ts initGlobalAPI()


/**
* 初始化 Vue 的众多全局 API,比如:
* 默认配置:Vue.config
* 工具方法:Vue.util.xx
* Vue.set、Vue.delete、Vue.nextTick、Vue.observable
* Vue.options.components、Vue.options.directives、Vue.options.filters、Vue.options._base
* Vue.use、Vue.extend、Vue.mixin、Vue.component、Vue.directive、Vue.filter
*
*/

export function initGlobalAPI(Vue: GlobalAPI) {
// config
const configDef: Record<string, any> = {}
configDef.get = () => config
if (__DEV__) {
configDef.set = () => {
warn(
'Do not replace the Vue.config object, set individual fields instead.'
)
}
}
Object.defineProperty(Vue, 'config', configDef)

// exposed util methods.
// NOTE: these are not considered part of the public API - avoid relying on
// them unless you are aware of the risk.
Vue.util = {
warn,
extend,
mergeOptions,
defineReactive
}

Vue.set = set
Vue.delete = del
Vue.nextTick = nextTick

// 2.6 explicit observable API
Vue.observable = <T>(obj: T): T => {
observe(obj)
return obj
}

Vue.options = Object.create(null)
ASSET_TYPES.forEach(type => {
Vue.options[type + 's'] = Object.create(null)
})

// this is used to identify the "base" constructor to extend all plain-object
// components with in Weex's multi-instance scenarios.
Vue.options._base = Vue

// 在 Vue.options.components 中添加内置组件,比如 keep-alive
extend(Vue.options.components, builtInComponents)

initUse(Vue)
initMixin(Vue)
initExtend(Vue)
initAssetRegisters(Vue)
}

三、src/core/global-api/use.ts initUse()


/**
* 定义 Vue.use,负责为 Vue 安装插件,做了以下两件事:
* 1、判断插件是否已经被安装,如果安装则直接结束
* 2、安装插件,执行插件的 install 方法
* @param {*} plugin install 方法 或者 包含 install 方法的对象
* @returns Vue 实例
*/

export function initUse(Vue: GlobalAPI) {
Vue.use = function (plugin: Function | any) {
// 已经安装过的插件列表
const installedPlugins =
this._installedPlugins || (this._installedPlugins = [])
// 判断 plugin 是否已经安装,保证不重复安装
if (installedPlugins.indexOf(plugin) > -1) {
return this
}

// 将 Vue 构造函数放到第一个参数位置,然后将这些参数传递给 install 方法
const args = toArray(arguments, 1)
args.unshift(this)
if (isFunction(plugin.install)) {
// plugin 是一个对象,则执行其 install 方法安装插件
plugin.install.apply(plugin, args)
} else if (isFunction(plugin)) {
// 执行直接 plugin 方法安装插件
plugin.apply(null, args)
}
// 在 插件列表中 添加新安装的插件
installedPlugins.push(plugin)
return this
}
}