vue核心源码解读二

339 阅读1分钟

本节开始,我们进入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所做的事情