Vue源码解析-Vue和实例对象

2020-03-05  本文已影响0人  kruz

先看一下源码中关于Vue函数的定义(稍稍简化),摘自Vue 2.6.11。

 function Vue (options) {
    if (!(this instanceof Vue)
    ) {
      warn('Vue is a constructor and should be called with the `new` keyword');
    }
    this._init(options); // 调用Vue.prototype._init函数, this指向的就是Vue实例对象了
  }

  //调用一系列方法
  initMixin(Vue);   // 初始化,调用initMixin函数,传入Vue构造函数
  stateMixin(Vue);
  eventsMixin(Vue);
  lifecycleMixin(Vue);
  renderMixin(Vue);

 function initMixin (Vue) {
    Vue.prototype._init = function (options) {
      var vm = this; // vm被赋值为实例对象
      vm._uid = uid$3++;  //  当触发init方法,新建Vue实例时(当渲染组件时也会触发)uid都会递增

      // 加入标志防止该对象对observer监听
      vm._isVue = true;
      // 合并options
      if (options && options._isComponent) {  // 当是组件时
        // optimize internal component instantiation
        // since dynamic options merging is pretty slow, and none of the
        // internal component options needs special treatment.
        initInternalComponent(vm, options);
      } else {     // 当不是组件时
       // 将合并后的options赋值給实例对象的$options
        vm.$options = mergeOptions(
          resolveConstructorOptions(vm.constructor),
          options || {},
          vm
        );
      }
     
      initProxy(vm);
      // 实例对象的_self指向自己, 暴露出去
      // 各种初始化
      initLifecycle(vm); 
      initEvents(vm);
      initRender(vm);
      callHook(vm, 'beforeCreate'); // 触发beforeCreate生命周期函数
      initInjections(vm); // resolve injections before data/props
      initState(vm);
      initProvide(vm); // resolve provide after data/props
      callHook(vm, 'created'); // 触发created生命周期函数

      // 挂载el
      if (vm.$options.el) {
        vm.$mount(vm.$options.el);
      }
    };
  }

看看

Vue就是一个函数,当然可以把它理解为构造函数和类,她只能用new 来生成实例对象。

我们平常使用引入Vue的方式就是:

var vm = new Vue({
      el: '#app',
      data: {
          showA: false
      },
      beforeCreate(){
      },
      created(){
      },
       mounted(){
       },
       methods: {
       }
});
// 可以打印出如下的数据
console.log(vm instanceof Vue); // true;   
console.log(vm._self === vm); // true;
console.log(vm._isVue); // true;
console.log(vm._uid ); // 0; // 只有一个实例且没有组件就是0
console.log(vm.$options); //  生成后的options

_init函数最重要的两个部分就是:

1.初始化各种状态,然后调用beforeCreatedcreated 生命周期函数。
2.合并options生成 $options, 然后挂载。

看看$options的由来:

 vm.$options = mergeOptions(
          resolveConstructorOptions(vm.constructor),
          options || {},
          vm
);

resolveConstructorOptions函数生成的对象含有:components,directives, filters
然后再进行合并:
最后得出的$options,含有:

{
  components: {}
  directives: {}
  filters: {}
  _base: ƒ Vue(options)
  el: "#app"
  data: ƒ mergedInstanceDataFn()
  mounted: [ƒ]
  methods: { beforeEnter: ƒ, enter: ƒ, leave: ƒ, changeShow: ƒ}
  render: ƒ anonymous( )
  staticRenderFns: []
}

然后去调用$amount函数,执行挂载。

上一篇下一篇

猜你喜欢

热点阅读