持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第29天,点击查看活动详情
想要了解new Vue(options) 发生了什么,其实就是需要从源码去理解vue的初始化过程。本文则从入口开始,一步步带你了解。
入口:vue构造函数
/src/core/instance/index.ts
这个构造函数执行了init方法,Vue.prototype._init实际上是在initMixin方法定义的。所以可以看到整个初始化过程其实就是在initMixin方法中,那我们就从这一函数中来找答案。
initMixin Vue.prototype._init
/src/core/instance/init.ts
下文对源码做了部分删减,只保留重要的部分。
export function initMixin(Vue: typeof Component) {
Vue.prototype._init = function (options?: Record<string, any>) {
const vm: Component = this
//每个 vue 实例都有一个 _uid,并且是依次递增的
vm._uid = uid++
……
vm._isVue = true
//处理组件配置项
if (options && options._isComponent) {
//子组件:性能优化,减少原型链的动态查找,提高执行效率
initInternalComponent(vm, options as any)
} else {
//根组件走这里:选项合并,将全局配置选项合并到根组件的局部配置上
vm.$options = mergeOptions(
resolveConstructorOptions(vm.constructor as any),
options || {},
vm
)
}
……
vm._self = vm
//组件实例关系属性, 如 $parent、$children、$root、$refs等,这里并不是生命周期函数的初始化
initLifecycle(vm)
//初始化自定义事件
initEvents(vm)
//初始化插槽,获取this.$slots,定义this._c,即createElement方法,平时使用的h函数
initRender(vm)
//执行beforeCreate生命周期函数
callHook(vm, 'beforeCreate', undefined, false /* setContext */)
//初始化inject选项
initInjections(vm)
//响应式原理的入口,处理 props、methods、data、computed、watch
initState(vm)
//解析组件配置项上的 provide 对象,将其挂载到 vm._provided 属性上
initProvide(vm)
//执行create生命周期函数
callHook(vm, 'created')
……
//挂载
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
}
}
总结
最后根据源码总结一下Vue 的初始化过程:
-
处理组件配置项
-
初始化组件实例的关系属性,比如
$parent、$children、$root、$refs等 -
初始化自定义事件
-
调用
beforeCreate生命周期钩子函数 -
初始化组件的 inject 配置项
-
数据响应式处理,处理 props、methods、data、computed、watch 等选项
-
解析组件配置项上的 provide 对象
-
调用 created 生命周期钩子函数
-
如果发现配置项上有 el 选项,则自动调用
$mount方法,也就是说有了 el 选项,就不需要再手动调用$mount方法,反之,没提供 el 选项则必须调用$mount -
最后进入挂载阶段