这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战
前言
在前边看new Vue实例的过程中已经了解到在创建Vue实例以后首先就进入初始化阶段。在这个阶段会调用_init方法,里边有几个初始化函数。
_init方法是定义在Vue原型上的,在src/core/instance/init.js
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')
在看代码之前,先来看下Vue官方提供的生命周期图中关于初始化这块的流程图:
这个图完美的展现了_init方法中初始化参数与钩子函数执行的顺序:
-
初始化生命周期与事件(initLifecyle + initEvents + initRender)
-
执行beforeCreate钩子函数
-
初始化injections与响应式(initInjections + initState + initProvide)
-
执行created钩子函数
接下来就来具体看下这几个初始化函数的具体实现,由于内容过多,这篇文先只看是如何初始化生命周期。先来看下initLifecycle方法:
initLifecycle
initLifecycle定义在src/core/instance/lifecycle.js中。
export function initLifecycle (vm: Component) {
const options = vm.$options
// locate first non-abstract parent
let parent = options.parent
if (parent && !options.abstract) {
while (parent.$options.abstract && parent.$parent) {
parent = parent.$parent
}
parent.$children.push(vm)
}
vm.$parent = parent
vm.$root = parent ? parent.$root : vm
vm.$children = []
vm.$refs = {}
vm._watcher = null //渲染Watcher
vm._inactive = null //缓存组件相关,标志是否被激活
vm._directInactive = false
vm._isMounted = false
vm._isDestroyed = false
vm._isBeingDestroyed = false //标志是否正在被销毁,介于生命周期beforeDestroy与destroyed之间
}
代码很简单,主要分为两部分:
-
初始化当前vm实例的祖先关系以及refs属性
-
初始化生命周期钩子相关的变量
值的关注的是在建立组件的父子关系时,会先判断当前vm的abstract是否为true。如果当前vm实例abstract属性为false,则还要while循环去判断父组件的abstract属性,如果为true则会一直向上找,直到找到abstract为false的父组件为止。
如果组件设置了abstract为true,即代表它是一个抽象组件,如keep-alive,transition等,则直接跳过,不关联父子关系。这就是为什么官方说keep-alive抽象组件是不会出现在组件的父组件链中。