Vue 全局API

书接上回, 从之前分析Vue构造函数那篇起,回溯之前调用src/core/instance/index.jssrc/core/index.js

现在我们打开src/core/index.js,看到这个文件引入了如下的内容:

1
2
3
4
5
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'

这部分有什么奥妙?

Vue全局API

看到这行 initGlobalAPI(Vue),在src/core/instance/index.js export出来的Vue初始化了全局API

下面对ssr的情况进行判断处理:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// core/index.js 文件中
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
})

同理,对SSR的$isServer$ssrContext也是只读的。

最后的

1
2
Vue.version = '__VERSION__'

则是用打包工具在相应的环境替换成对应的版本号。

这里,我们主要重点关注全局API的具体实现。

打开 src/core/global-api/index.js,这里是全局API实现的入口文件。 首先是引入配置:import config from '../config'

src/core/global-api/的文件夹下面,还分别有4个文件,我们可以看到index.js的开头引入了这些文件:

1
2
3
4
import { initUse } from './use'
import { initMixin } from './mixin'
import { initExtend } from './extend'
import { initAssetRegisters } from './assets'

这部分是全局api的一些功能实现,被拆分到几个部分。

接下来,看到下面几行

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import { set, del } from '../observer/index'
import { ASSET_TYPES } from 'shared/constants'
import builtInComponents from '../components/index'

import {
  warn,
  extend,
  nextTick,
  mergeOptions,
  defineReactive
} from '../util/index'

这些引入的模块具体是做什么的,我们顺着下面的代码读下去应该就能知道。

在文件的20行左右,是一个函数 export function initGlobalAPI (Vue: GlobalAPI) {...} 见名知意,这个函数就是负责初始化全局API。 函数参数后的GlobalAPI是Flow的 Interface,用来检查和GlobalAPI相关的类型的。

下面看到函数内部的实现:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 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)

这里的configDef,注意,是configDefconfigDef是类似这前一章分析过的那样,利用了defineProperty()方法和存取器属性(accessor property)。在非生产环境企图修改configDef会有个警告。关于config的具体分析,笔者会在另一篇文章中详述。

下面继续向下看,

1
2
3
4
5
6
7
8
9
 // 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自己的一些util方法。但是注释告知了,这些方法不属于公共API,要避免依赖于这样方法。

下面是:

1
2
3
 Vue.set = set
 Vue.delete = del
  Vue.nextTick = nextTick

setdel 分别来自: import { set, del } from '../observer/index'nextTick 来自'../util/index'

接下来是

1
Vue.options = Object.create(null)