本节开始,我们进入vue最核心代码的解读,源码路径
core/instance/index.js
挂载mixin
首先,vue是一个函数(类),在调用时会执行_init方法初始化
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)
}
在模块暴露出Vue之前,首先为Vue添加各种mixin的能力
initMixin(Vue)
stateMixin(Vue)
eventsMixin(Vue)
lifecycleMixin(Vue)
renderMixin(Vue)
initMixin
进入initMixin模块,我们可以看到,initMixin方法的主要目的,就是为Vue原型挂载_init方法,这样在实例话Vue组件的时候,就可以调用_init做一些初始化操作,我们暂时先不要去深入关注init方法做了什么
export function initMixin (Vue: Class<Component>) {
Vue.prototype._init = function (options?: Object) {
//......
}
}
stateMixin
进入stateMixin模块,依旧是,我们暂时忽略实现细节,stateMixin方法做的事情,就是给Vue的原型上挂载$data,$props,$set,$delete,$watch等一些和组件状态关系密切的属性方法
export function stateMixin (Vue: Class<Component>) {
const dataDef = {}
dataDef.get = function () { return this._data }
const propsDef = {}
propsDef.get = function () { return this._props }
if (process.env.NODE_ENV !== 'production') {
dataDef.set = function () {
warn(
'Avoid replacing instance root $data. ' +
'Use nested data properties instead.',
this
)
}
propsDef.set = function () {
warn(`$props is readonly.`, this)
}
}
Object.defineProperty(Vue.prototype, '$data', dataDef)
Object.defineProperty(Vue.prototype, '$props', propsDef)
Vue.prototype.$set = set
Vue.prototype.$delete = del
Vue.prototype.$watch = function (
expOrFn: string | Function,
cb: any,
options?: Object
): Function {
// ......
}
}
eventsMixin
进入eventsMixin,我们可以看到,eventsMixin方法做的事情,就是为Vue原型上挂载$on,$once,$off,$emit这些我们所熟知的和事件相关的方法
export function eventsMixin (Vue: Class<Component>) {
Vue.prototype.$on = function (event: string | Array<string>, fn: Function): Component {
// ......
}
Vue.prototype.$once = function (event: string, fn: Function): Component {
// ......
}
Vue.prototype.$off = function (event?: string | Array<string>, fn?: Function): Component {
// ......
}
Vue.prototype.$emit = function (event: string): Component {
// ......
}
}
lifecycleMixin
从名字可以看出来,这个mixin主要就是和声明周期相关的内容了,如下面代码,可以看到,lifecycleMixin方法就是为Vue的原型挂载_update,$forceUpdata,$destory这些操作生命周期相关的方法
export function lifecycleMixin (Vue: Class<Component>) {
Vue.prototype._update = function (vnode: VNode, hydrating?: boolean) {
// ......
}
Vue.prototype.$forceUpdate = function () {
// ......
}
Vue.prototype.$destroy = function () {
// ......
}
}
renderMixin
我们可以看到,renderMixin方法,主要是为Vue的原型上添加$nextTick,_render方法,都是和vue实例渲染相关的方法
export function renderMixin (Vue: Class<Component>) {
// 为Vue运行时提供一些遍历的辅助功能函数
installRenderHelpers(Vue.prototype)
Vue.prototype.$nextTick = function (fn: Function) {
// ......
}
Vue.prototype._render = function (): VNode {
// ......
}
}
从下一节开始,我们会深入每个mixin模块内部,去详细的解析这些mixin所做的事情