1、首先找到Vue的构造函数
源码位置:src\core\instance\index.js
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)
}
options是用户传递过来的配置项,如data、methods等常用的方法
在下面还定义了一些初始化的方法
// 定义Vue原型上的init方法(内部方法)
initMixin(Vue);
// 定义原型上跟数据相关的属性方法
stateMixin(Vue);
//定义原型上跟事件相关的属性方法
eventsMixin(Vue);
// 定义原型上跟生命周期相关的方法
lifecycleMixin(Vue);
// 定义渲染相关的函数
renderMixin(Vue);
2、_init方法是在initMixin中定义的,所以接下来看到initMixin方法
源码位置:src\core\instance\init.js
export function initMixin (Vue) {
Vue.prototype._init = function (options) {
const vm = this
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor),
options || {},
vm
)
vm._self = vm
initLifecycle(vm)
initEvents(vm)
initRender(vm)
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
首先,把Vue实例赋值给变量vm,并且把用户传递的options选项与当前构造函数的options属性及其父级构造函数的options属性进行合并,得到一个新的options选项赋值给$options属性,并将$options属性挂载到Vue实例上,如下:
3、调用mergeOptions函数来进行属性合并
function mergeOptions (parent,child,vm) {
{
checkComponents(child);
}
if (typeof child === 'function') {
child = child.options;
}
// props,inject,directives的校验和规范化
normalizeProps(child, vm);
normalizeInject(child, vm);
normalizeDirectives(child);
// 针对extends扩展的子类构造器
if (!child._base) {
// extends
if (child.extends) {
parent = mergeOptions(parent, child.extends, vm);
}
// mixins
if (child.mixins) {
for (var i = 0, l = child.mixins.length; i < l; i++) {
parent = mergeOptions(parent, child.mixins[i], vm);
}
}
}
var options = {};
var key;
for (key in parent) {
mergeField(key);
}
for (key in child) {
if (!hasOwn(parent, key)) {
mergeField(key);
}
}
function mergeField (key) {
// 拿到各个选择指定的选项配置,如果没有则用默认的配置
var strat = strats[key] || defaultStrat;
// 执行各自的合并策略
options[key] = strat(parent[key], child[key], vm, key);
}
// console.log(options)
return options
}
接着,通过调用一些初始化函数来为Vue实例初始化一些属性,事件,响应式数据等,如下
initLifecycle(vm) // 初始化生命周期
initEvents(vm) // 初始化事件
initRender(vm) // 初始化渲染
callHook(vm, 'beforeCreate') // 调用生命周期钩子函数
initInjections(vm) //初始化injections
initState(vm) // 初始化props,methods,data,computed,watch
initProvide(vm) // 初始化 provide
callHook(vm, 'created') // 调用生命周期钩子函数
4、调用$mount开启下一生命周期
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
在所有的初始化工作都完成以后,最后,会判断用户是否传入了el选项,如果传入了则调用$mount函数进入模板编译与挂载阶段,如果没有传入el选项,则不进入下一个生命周期阶段,需要用户手动执行vm.$mount方法才进入下一个生命周期阶段。