vue源码解析pdf_Vue源码全面解析八 callHook函数(触发生命周期函数)

首先我们打开‘src/core/instance/lifecycle.js'文件,代码如下:
export function callHook (vm: Component, hook: string) { pushTarget() const handlers = vm.$options[hook] const info = `${hook} hook` if (handlers) { for (let i = 0, j = handlers.length; i < j; i++) { invokeWithErrorHandling(handlers[i], vm, null, vm, info) } } if (vm._hasHookEvent) { vm.$emit('hook:' + hook) } popTarget()}
可以看到这个函数比较简单,主要有3点:
1、禁止Dep的依赖收集
2、调用 "invokeWithErrorHandling" 触发对应的生命周期函数
3、触发对应是钩子函数,如果存在的话
pushTarget()// 函数代码如下export function pushTarget (target: ?Watcher) { targetStack.push(target) Dep.target = target}
可以看调用该函数的时候没有传任何参数,那就是 “target” 参数的 “undefined”,就没有收集对象了。
const handlers = vm.$options[hook]const info = `${hook} hook`
定义了 “handlers” 和 “info” 两个变量,分别存储生命周期函数和事件描述。
if (handlers) { for (let i = 0, j = handlers.length; i < j; i++) { invokeWithErrorHandling(handlers[i], vm, null, vm, info) } }
可以看到 “handlers” 如果存在的话,那肯定是一个数组的形式,这里会遍历数组来进行调用。
vue官网说的是每个生命周期钩子都是函数类型,但是我们从这里看出来其实也可以是函数数组,例如:
beforeCreate:[
() => {conosle.log("beforeCreate1")},
() => {conosle.log("beforeCreate2")},
]
你会看到数组里面的两个函数都被执行了。
if (vm._hasHookEvent) { vm.$emit('hook:' + hook) }
如果存在"hook" 钩子函数,则调用相关的事件
钩子函数的名称必须已 "hook:"开头,后面接对应的生命周期名称,例如:
this.$on("hook:mounted", () => {})
钩子函数必须注册在对应的生命周期函数内,或者之后的生命周期内定义才有效。
popTarget()// 代码如下export function popTarget () { targetStack.pop() Dep.target = targetStack[targetStack.length - 1]}
最后是恢复Dep的依赖收集。把之前的 “target” 等于undefined移除掉。