Vue 源码理解之new Vue

240 阅读1分钟

源码解析应从入口开始,一般在 main.js 文件中可见如下代码,其实 Vue 是class,new Vue 是实例化一个类,获得vm实例(而js中的class是通过function的方式实现的)

__ 代码1 __

import Vue from 'vue'

// 实例化Vue对象
new Vue({
  el: '#app',
  mounted() {
    console.log(this.message);
  },
  data: {
    message: 'Hello Vue!'
  }
})

__ 代码2 __

function Vue (options) { // Vue Class
  if (process.env.NODE_ENV !== 'production' &&
    !(this instanceof Vue)
  ) {
    warn('Vue is a constructor and should be called with the `new` keyword');
  }
  // 第2步:_init是定义在vue原型上的方法,它是在initMixin的时候绑定上去的
  this._init(options); 
}
// 先执行这些mixin操作
initMixin(Vue); // 第1步:把_init绑定到Vue原型上
stateMixin(Vue);
eventsMixin(Vue);
lifecycleMixin(Vue);
renderMixin(Vue);

如图1所示,在init方法中共做了以下几件事:

(1)定义uid

(2)合并options,使得new Vue中的options,可通过vm.$options.el/data直接访问

(3)各种初始化(生命周期,events,render,执行beforeCreated钩子函数,injections,state,provide,执行created钩子函数)

(4)执行$mount(注意执行前后,Html页面的变化)

—图1—

【问】从上面内容可知:可通过vm.$options.data.message获取,但为何this.message也可获取到值呢?

总结图2内容:

(1)_init方法中 => initState => initData,取出vm.$options.data,存于vm._data以及data

(2)使用proxy(vm, '_data', key)进行取值,即proxyGetter方法:this[_data][message]。并为data内部的值用Object.definProperty进行处理(为将来的响应式做准备)

—图2—