Vue构造函数的创建过程

821 阅读3分钟

写在前面

上一篇文章 《一口气看完Vue源码》 中对大体流程做了个分析,但由于过程太过冗长导致文件零散,所以可能还不了解 Vue构造函数 中的某些值是哪儿来的。这一章节主要讲的是 Vue构造函数 的创建,会从生成到添加属性完毕的顺序依次介绍每个文件中对 Vue构造函数 的操作。

core/instance/index.js

  • 创建 Vue 的构造函数
Vue = {}

core/instance/init.js

  • 给 Vue 的原型上添加 _init 方法
Vue = {
  prototype: {
    /* new add start */
    _init() {}
    /* new add end */
  }
}

core/instance/state.js

  • 给 Vue 的原型上添加 $data ( 获取 options._data )
  • 给 Vue 的原型上添加 $props ( 获取 options._props )
  • 给 Vue 的原型上添加 $set 方法 ( 解决对象和数组在设置新内容时无法触发依赖的问题 )
  • 给 Vue 的原型上添加 $del 方法 ( 解决对象在删除时无法触发依赖的问题 )
  • 给 Vue 的原型上添加 $watch 方法
Vue = {
  prototype: {
    _init() {},
    /* new add start */
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    /* new add end */
  }
}

core/instance/events.js

  • 给 Vue 的原型上添加 $on 方法 ( 发布订阅 - 订阅事件 )
  • 给 Vue 的原型上添加 $once 方法 ( 发布订阅 - 订阅一次性事件 )
  • 给 Vue 的原型上添加 $off 方法 ( 发布订阅 - 取消事件 )
  • 给 Vue 的原型上添加 $emit 方法 ( 发布订阅 - 发布事件 )
Vue = {
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    /* new add start */
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    /* new add end */
  }
}

core/instance/lifecycle.js

  • 给 Vue 的原型上添加 _update 方法 ( 组件更新时触发 )
  • 给 Vue 的原型上添加 $forceUpdate 方法 ( 组件强制更新时触发 )
  • 给 Vue 的原型上添加 $destroy 方法 ( 组件销毁时触发 )
Vue = {
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    /* new add start */
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    /* new add end */
  }
}

core/instance/render.js

  • 给 Vue 的原型上添加 $nextTick 方法 ( 解决异步渲染获取不到 DOM 元素的问题 )
  • 给 Vue 的原型上添加 _render 方法 ( 创建 虚拟DOM )
Vue = {
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    /* new add start */
    $nextTick() {},
    _render() {},
    /* new add end */
  }
}

core/instance/render-helpers/index.js

  • 给 Vue 的原型上添加上一堆模板编译过程中的辅助方法
Vue = {
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    $nextTick() {},
    _render() {},
    /* new add start */
    _o() {},
    _n() {},
    _s() {},
    _l() {},
    _t() {},
    _q() {},
    _i() {},
    _m() {},
    _f() {},
    _k() {},
    _b() {},
    _v() {},
    _e() {},
    _u() {},
    _g() {},
    /* new add end */
  }
}

core/index.js

  • 给 Vue 的原型上添加 $isServer ( 判断是否是服务器渲染 )
  • 给 Vue 的原型上添加 $ssrContext ( 获取服务器渲染的 虚拟DOM 上下文 )
  • 给 Vue 的构造函数上添加 version ( 获取当前 Vue 版本 )
Vue = {
  /* new add start */
  version: '__VERSION__',
  /* new add end */
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    $nextTick() {},
    _render() {},
    _o() {},
    _n() {},
    _s() {},
    _l() {},
    _t() {},
    _q() {},
    _i() {},
    _m() {},
    _f() {},
    _k() {},
    _b() {},
    _v() {},
    _e() {},
    _u() {},
    _g() {},
    /* new add start */
    $isServer: false,
    $ssrContext: {},
    /* new add end */
  }
}

core/global-api/index.js

  • 给 Vue 的构造函数上添加 config ( 内置一堆未定义的方法和属性 )
  • 给 Vue 的构造函数上添加 util ( 内置 warn / extend / mergeOptions / defineReactive 方法 )
  • 给 Vue 的构造函数上添加 set 方法 ( 同上给 Vue 的原型上添加 $set 方法一致 )
  • 给 Vue 的构造函数上添加 delete 方法 ( 同上给 Vue 的原型上添加 $del 方法一致 )
  • 给 Vue 的构造函数上添加 nextTick 方法 ( 同上给 Vue 的原型上添加 $nextTick 方法一致 )
  • 给 Vue 的构造函数上添加 options
  • 给 Vue 的构造函数上添加 options.components ( 放置全局组件 )
  • 给 Vue 的构造函数上添加 options.directives ( 放置全局指令 )
  • 给 Vue 的构造函数上添加 options.filters ( 放置全局过滤器 )
  • 给 Vue 构造函数上的 options 添加 _base 指向 Vue构造函数
  • 给 Vue 构造函数上的 options.components 全局组件 ( <keep-alive /> )
  • 给 Vue 的构造函数上添加 use 方法 ( 注册全局插件 - Vue.use )
  • 给 Vue 的构造函数上添加 mixin 方法 ( 注册全局混入 - Vue.mixin )
  • 给 Vue 的构造函数上添加 extend 方法 ( 注册继承自 Vue构造函数 的子类 - Vue.extend )
  • 给 Vue 的构造函数上添加 component 方法 ( 注册全局组件 - Vue.component )
  • 给 Vue 的构造函数上添加 directive 方法 ( 注册全局指令 - Vue.directive )
  • 给 Vue 的构造函数上添加 filter 方法 ( 注册全局过滤器 - Vue.filter )
Vue = {
  version: '__VERSION__',
  /* new add start */
  config: {
    // ...
  },
  util: {
    warn,
    extend,
    mergeOptions,
    defineReactive,
  },
  set(): {},
  delete(): {},
  nextTick(): {},
  options: {
    _base: Vue,
    components: {
      KeepAlive,
    }
    directives: {}
    filters: {}
  },
  use() {},
  mixin() {},
  extend() {},
  component() {},
  directive() {},
  filter() {},
  /* new add end */
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    $nextTick() {},
    _render() {},
    _o() {},
    _n() {},
    _s() {},
    _l() {},
    _t() {},
    _q() {},
    _i() {},
    _m() {},
    _f() {},
    _k() {},
    _b() {},
    _v() {},
    _e() {},
    _u() {},
    _g() {},
    $isServer: false,
    $ssrContext: {},
  }
}

platforms/web/runtime/index.js

  • 修改 Vue 构造函数上 config 内的 mustUseProp 的方法 ( 判断当前 tag 是否必须使用属性 )
  • 修改 Vue 构造函数上 config 内的 isReservedTag 的方法 ( 判断是否是保留标签 ( HTML标签 + SVG标签 ) )
  • 修改 Vue 构造函数上 config 内的 isReservedAttr 的方法 ( 判断是否是保留属性 ( style + class ) )
  • 修改 Vue 构造函数上 config 内的 getTagNamespace 的方法 ( 获取标签命名空间 )
  • 修改 Vue 构造函数上 config 内的 isUnknownElement 的方法 ( 判断是否是个无效标签 )
  • 给 Vue 构造函数上 options.components 添加 platformComponents 内的定义的全局组件 ( <Transition> + <TransitionGroup> )
  • 给 Vue 构造函数上 options.directives 添加 platformDirectives 内的定义的全局指令 ( v-model + v-show )
  • 给 Vue 的原型上添加 _patch_ 方法 ( diff 算法入口,提供虚拟节点的对比更新功能 )
  • 给 Vue 的原型上添加 $mount 方法 ( 创建 渲染Watcher,以便于数据驱动视图 )
Vue = {
  version: '__VERSION__',
  config: {
    /* update start */
    mustUseProp() {},
    isReservedTag() {},
    isReservedAttr() {},
    getTagNamespace() {},
    isUnknownElement() {},
    /* update end */
  },
  util: {
    warn,
    extend,
    mergeOptions,
    defineReactive,
  },
  set(): {},
  delete(): {},
  nextTick(): {},
  options: {
    _base: Vue,
    components: {
      KeepAlive,
      /* new add start */
      Transition,
      TransitionGroup,
      /* new add end */
    }
    /* new add start */
    directives: {
      'model',
      'show',
    }
   /* new add end */
    filters: {}
  },
  use() {},
  mixin() {},
  extend() {},
  component() {},
  directive() {},
  filter() {},
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    $nextTick() {},
    _render() {},
    _o() {},
    _n() {},
    _s() {},
    _l() {},
    _t() {},
    _q() {},
    _i() {},
    _m() {},
    _f() {},
    _k() {},
    _b() {},
    _v() {},
    _e() {},
    _u() {},
    _g() {},
    $isServer: false,
    $ssrContext: {},
    /* new add start */
    __patch__() {},
    $mount() {},
    /* new add end */
  }
}

platforms/web/entry-runtime-with-compiler.js

  • 修改 Vue 原型上的 $mount 方法
  • 给 Vue 的构造函数上添加 compile 方法
Vue = {
  version: '__VERSION__',
  config: {
    mustUseProp() {},
    isReservedTag() {},
    isReservedAttr() {},
    getTagNamespace() {},
    isUnknownElement() {},
  },
  util: {
    warn,
    extend,
    mergeOptions,
    defineReactive,
  },
  set(): {},
  delete(): {},
  nextTick(): {},
  options: {
    _base: Vue,
    components: {
      KeepAlive,
      Transition,
      TransitionGroup,
    }
    directives: {
      'model',
      'show',
    }
    filters: {}
  },
  use() {},
  mixin() {},
  extend() {},
  component() {},
  directive() {},
  filter() {},
  /* new add start */
  compile() {},
  /* new add end */
  prototype: {
    _init() {},
    $data: {},
    $props: {},
    $set() {},
    $del() {},
    $watch() {},
    $on() {},
    $once() {},
    $off() {},
    $emit() {},
    _update() {},
    $forceUpdate() {},
    $destroy() {},
    $nextTick() {},
    _render() {},
    _o() {},
    _n() {},
    _s() {},
    _l() {},
    _t() {},
    _q() {},
    _i() {},
    _m() {},
    _f() {},
    _k() {},
    _b() {},
    _v() {},
    _e() {},
    _u() {},
    _g() {},
    $isServer: false,
    $ssrContext: {},
    __patch__() {},
    /* update start */
    $mount() {},
    /* update end */
  }
}

自此,一个完整的 Vue构造函数 就创建完毕了。