寻找 Vue 的入口
-
src/platforms/web/entry-runtime-with-compiler
文件,它虽然export default Vue
,但是先从./runtime/index
import 了 Vue
import Vue from './runtime/index'
-
runtime/index
从core/index
中 import 了 Vue
import Vue from 'core/index'
-
core/index
从instance/index
中 import Vue ,并初始化全局 API ,给 Vue 这个对象本身扩展全局的静态方法
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'
initGlobalAPI(Vue)
-
instance/index
中我们会发现, Vue实际上是一个 Function 实现的类,我们只能通过 new Vue 去实例化它,为什么不用 class 来定义 Vue 呢
因为有很多 xxxMixin 的函数调用,把 Vue 当参数传入,它们的功能都是给 Vue 的 prototype 上扩展一些方法,Vue 按功能把这些扩展分散到多个模块中去实现,而不是在一个模块里实现所有,这种方式是用 Class 难以实现的。这么做的好处是非常方便代码的维护和管理
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 的入口
- 那么一系列的 mixin 函数又做了什么呢,我在下面做了个总结
// initMixin(Vue) src/core/instance/init.js **************************************************
Vue.prototype._init = function (options?: Object) {}
// stateMixin(Vue) src/core/instance/state.js **************************************************
Vue.prototype.$data
Vue.prototype.$set = set
Vue.prototype.$delete = del
Vue.prototype.$watch = function(){}
// renderMixin(Vue) src/core/instance/render.js **************************************************
Vue.prototype.$nextTick = function (fn: Function) {}
Vue.prototype._render = function (): VNode {}
Vue.prototype._s = _toString
Vue.prototype._v = createTextVNode
Vue.prototype._n = toNumber
Vue.prototype._e = createEmptyVNode
Vue.prototype._q = looseEqual
Vue.prototype._i = looseIndexOf
Vue.prototype._m = function(){}
Vue.prototype._o = function(){}
Vue.prototype._f = function resolveFilter (id) {}
Vue.prototype._l = function(){}
Vue.prototype._t = function(){}
Vue.prototype._b = function(){}
Vue.prototype._k = function(){}
// eventsMixin(Vue) src/core/instance/events.js **************************************************
Vue.prototype.$on = function (event: string, fn: Function): Component {}
Vue.prototype.$once = function (event: string, fn: Function): Component {}
Vue.prototype.$off = function (event?: string, fn?: Function): Component {}
Vue.prototype.$emit = function (event: string): Component {}
// lifecycleMixin(Vue) src/core/instance/lifecycle.js **************************************************
Vue.prototype._mount = function(){}
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {}
Vue.prototype._updateFromParent = function(){}
Vue.prototype.$forceUpdate = function () {}
Vue.prototype.$destroy = function () {}
- 知道了 Vue 的构造函数以及一系列的 mixin 做了什么之后 ,我们在回溯到上一个,及
core/index.js
中
initGlobalAPI(Vue)
- initGlobalAPI 的作用是在 Vue 构造函数上挂载静态属性和方法,经历过initGlobalAPI 后 Vue 如下
Vue.config
Vue.util = util
Vue.set = set
Vue.delete = del
Vue.nextTick = util.nextTick
Vue.observable
Vue.options = {
components: {
KeepAlive
},
directives: {},
filters: {},
_base: Vue
}
Vue.use
Vue.mixin
Vue.cid = 0
Vue.extend
Vue.component = function(){}
Vue.directive = function(){}
Vue.filter = function(){}
- 继续回溯,在
platforms/web/runtime.js
中主要做了三件事
一、覆盖 Vue.config 的属性,将其设置为平台特有的一些方法
二、Vue.options.directives 和 Vue.options.components 安装平台特有的指令和组件
三、在 Vue.prototype 上定义 _patch_ 和 $mount
- 这个时候的 Vue 又增加了新的属性
// 安装平台特定的utils
Vue.config.isUnknownElement = isUnknownElement
Vue.config.isReservedTag = isReservedTag
Vue.config.getTagNamespace = getTagNamespace
Vue.config.mustUseProp = mustUseProp
// 安装平台特定的 指令 和 组件
Vue.options = {
components: {
KeepAlive,
Transition,
TransitionGroup
},
directives: {
model,
show
},
filters: {},
_base: Vue
}
Vue.prototype.__patch__
Vue.prototype.$mount
- 最后我们回溯到了``entry-runtime-with-compiler````文件中,这个文件重要做了两件事
1、缓存来自 web-runtime.js 文件的 $mount 函数,
const mount = Vue.prototype.$mount
然后覆盖覆盖了 Vue.prototype.$mount
2、在 Vue 上挂载 compile
Vue.compile = compileToFunctions
,
compileToFunctions 函数的作用,就是将模板 template 编译为 render 函数
总结
- 至此我们将 Vue 构造函数做了简单的一轮梳理
Vue.prototype 下的属性和方法的挂载主要是在
src/core/instance
目录中的代码处理的
Vue 下的静态属性和方法的挂载主要是在
src/core/global-api
目录下的代码处理的
platforms/web/runtime/index.js
主要是添加 web 平台特有的配置、组件和指令,entry-runtime-with-compiler.js
给 Vue 的 $mount 方法添加 compiler 编译器,支持 template。
网友评论