最近在折腾Vue的项目,突然想聊聊一个话题:关于Vue入口与initGlobalAPI之间的一些事。
initGlobalAPI(Vue) 初始化Vue的全局静态API。平时开发通过 new Vue({...}) 去创建了根实例,当然在此之前,Vue已经做了一些前期的准备工作。Vue 的核心代码都在 src/core 目录中,我们先来看看 core/index.js 这个入口文件,这部分代码逻辑很简单。
Vue 的入口 {#heading-0}
在上面的scripts/alias
文件中可以分析出入口是:src/platforms/web/entry-runtime-with-compiler.js
import Vue from './runtime/index'
在这个入口 JS 的上方我们可以找到 Vue 的来源:import Vue from './runtime/index'
,我们先来看一下这块儿的实现,它定义在 src/platforms/web/runtime/index.js
中:
import Vue from 'core/index'
这里关键的代码是 import Vue from 'core/index'
,之后的逻辑都是对 Vue 这个对象做一些扩展,可以先不用看,我们来看一下真正初始化 Vue 的地方,在 src/core/index.js
中:
import Vue from './instance/index'
这里有 2 处关键的代码,import Vue from './instance/index'
和 initGlobalAPI(Vue)
,初始化全局 Vue API(我们稍后介绍),我们先来看第一部分,在 src/core/instance/index.js
中:
import { initMixin } from './init'
import { stateMixin } from './state'
import { renderMixin } from './render'
import { eventsMixin } from './events'
import { lifecycleMixin } from './lifecycle'
import { warn } from '../util/index'
function Vue (options) {
if (process.env.NODE_ENV !== 'production' &&
!(this instanceof Vue)
) {
warn('Vue is a constructor and should be called with the `new` keyword')
}
this._init(options)
}
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
export default Vue
在这里,我们终于看到了 Vue 的庐山真面目,它实际上就是一个用 Function 实现的类,我们只能通过 new Vue 去实例化它。
我们往后看这里有很多 xxxMixin 的函数调用,并把 Vue 当参数传入,它们的功能都是给 Vue 的 prototype 上扩展一些方法,Vue 按功能把这些扩展分散到多个模块中去实现,而不是在一个模块里实现所有
{#_label1}
initGlobalAPI {#heading-1}
Vue.js 在整个初始化过程中,除了给它的原型 prototype 上扩展方法,还会给 Vue 这个对象本身扩展全局的静态方法,它的定义在 src/core/global-api/index.js
中:
/* @flow */
import config from '../config'
import { initUse } from './use'
import { initMixin } from './mixin'
import { initExtend } from './extend'
import { initAssetRegisters } from './assets'
import { set, del } from '../observer/index'
import { ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'
import { observe } from 'core/observer/index'
import {
warn,
extend,
nextTick,
mergeOptions,
defineReactive
} from '../util/index'
export function initGlobalAPI (Vue: GlobalAPI) {
// config
const configDef = {}
configDef.get = () => config
if (process.env.NODE_ENV !== 'production') {
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
extend(Vue.options.components, builtInComponents)
initUse(Vue)
initMixin(Vue)
initExtend(Vue)
initAssetRegisters(Vue)
}
这里就是在 Vue 上扩展的一些全局方法的定义,Vue 官网中关于全局 API 都可以在这里找到。
总结 {#item-3}
这里主要讲的就是Vue
官网全局API
的内容,不算特别详细,但也一一介绍到了,如果要追求更深入的了解,可以去git
上下载一份源码钻研钻研,其实在继承那里,类似initProps
、initComputed
也是能提升项目中对Vue
用法的理解。