先看下这5个函数调用:
callHook(vm, 'beforeCreate')
initInjections(vm) // resolve injections before data/props
initState(vm)
initProvide(vm) // resolve provide after data/props
callHook(vm, 'created')复制代码
先看看callHook函数作用:调用生命周期钩子函数
下面是
callHook
函数源码
export function callHook (vm: Component, hook: string) {
// #7573 disable dep collection when invoking lifecycle hooks
pushTarget() //为了避免在某些生命周期钩子中使用 props 数据导致收集冗余的依赖
const handlers = vm.$options[hook] //获取生命周期钩子 vue选项合并会把生命周期钩子选项合并成一个数组
if (handlers) {
for (let i = 0, j = handlers.length; i < j; i++) {
try {
handlers[i].call(vm)//为了保证生命周期钩子函数内可以通过 this 访问实例对象,所以使用 .call(vm) 执行这些函数
} catch (e) { //为了捕捉可能出现的错误
handleError(e, vm, `${hook} hook`)
}
}
}
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook)
}
popTarget() //为了避免在某些生命周期钩子中使用 props 数据导致收集冗余的依赖
}复制代码
接收两个参数:实例对象和要调用的生命周期钩子的名称
现在大家应该知道,beforeCreate
以及 created
这两个生命周期钩子的调用时机了。
其中 initState
包括了:initProps
、initMethods
、initData
、initComputed
以及 initWatch
。
所以当 beforeCreate
钩子被调用时,所有与 props
、methods
、data
、computed
以及 watch
相关的内容都不能使用,当然了 inject/provide
也是不可用的。
created
生命周期钩子
initInjections
、initState
以及 initProvide
执行完毕之后才被调用,
所以在 created
钩子中,是完全能够使用以上提到的内容的。但由于此时还没有任何挂载的操作,但是在 created
中是不能访问DOM的,即不能访问 $el
。
callHook
函数最后一段代码
if (vm._hasHookEvent) {
vm.$emit('hook:' + hook)
}复制代码
vm._hasHookEvent
是在 initEvents
函数中定义的,它的作用是判断是否存在生命周期钩子的事件侦听器,初始化值为 false
代表没有,当组件检测到存在生命周期钩子的事件侦听器时,会将 vm._hasHookEvent
设置为 true
介绍下生命周期钩子事件帧听器:
<child
@hook:beforeCreate="handleChildBeforeCreate"
@hook:created="handleChildCreated"
@hook:mounted="handleChildMounted"
@hook:生命周期钩子
/>复制代码
使用hook:加上生命周期钩子名称来监听组件内对应的生命周期事件
接下来继续讲那几个调用函数:initState
initState执行前先执行了initInjections函数,也就是说inject选项更早被初始化,由于初始化inject设计到比较多 先跳过讲initstate
export function initState (vm: Component) {
vm._watchers = [] //在vue实例对象上添加一个属性(数组)
const opts = vm.$options //定义一个常量作为vm.$options引用
if (opts.props) initProps(vm, opts.props) //判断选项中是否有props 有则调用initprops
//判断是否有methods,有则调用initmethodds初始化methods选项 if (opts.methods) initMethods(vm, opts.methods)
if (opts.data) {//判断data是否存在 //调用initdata初始化data选项
initData(vm)
} else {//如果不存在则调用observe函数观察一个空对象
observe(vm._data = {}, true /* asRootData */)
}
if (opts.computed) initComputed(vm, opts.computed) //判断computed是否存在,然后初始化
if (opts.watch && opts.watch !== nativeWatch) { //判断是否存在和是否是原生对象...
initWatch(vm, opts.watch)
}
}复制代码
整理完initstate函数发现都是一些初始化选项汇总: