# 【源码】生命周期 源码解析
# 前言
生命周期的源码比较简单,这里就不从入口开始一步一步讲了
# 源码解析
我们知道Vue的mixin机制会把生命周期的回调函数存在一个数组中
vm.$options={
mounted:[fn,fn,fn...]
}
然后Vue源码是通过callHook
函数来调用这些回调,达到生命周期执行的效果, 如
Vue.prototype._init = function (options) {
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');
}
因为initState
的执行在beforeCreate
和 created
之间,所以在beforeCreate
生命周期里面是拿不到data数据的
我们来看一下callHook
函数
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()
}
从代码上我们可以发现两个点
内部很简单,是通过遍历数组的形式让生命周期的回调函数执行
向外暴露事件
hook
, 这也是为什么我们可以通过@hook
来获取到某个组件的生命周期的原因
我们对生命周期的原理有了大致了解之后,我们再来看下各个生命周期都在什么时候执行
// Vue初始化的时候
Vue.prototype._init(opt){
... 合并选项
... 设置初始值 ,事件 等数据
initLifecycle(vm)
callHook(vm, 'beforeCreate');
... 初始化选项等数据
callHook(vm, 'created');
...获取挂载的DOM 父节点
callHook(vm, 'beforeMount');
...解析模板成渲染函数,并执行渲染函数,生成DOM插入页面
vm._isMounted = true;
callHook(vm, 'mounted');
}
// 组件更新的时候
Vue.prototype._update = function(
vnode, hydrating
) {
if (vm._isMounted) {
callHook(vm, 'beforeUpdate');
}
...重新调用渲染函数,对比旧节点和新节点,得到最小差异,然后只更新这部分页面
callHook(vm, 'updated');
}
// 节点被移除时会调用这个函数
Vue.prototype.$destroy = function() {
callHook(vm, 'beforeDestroy');
vm._isBeingDestroyed = true;
...实例被消除,移除所有 watcher
vm._isDestroyed = true;
...DOM被移除
callHook(vm, 'destroyed');
}
# 总结
生命周期的源码超级简单,就是遍历mixin机制合并之后的生命周期回调函数数组,然后依次执行,但是我们也发现了另外一点就是我们可以通过@hook
获取到组件的生命周期