Vue3系列 - 生命周期钩子的实现
生命周期钩子的实现
Vue3中的生命周期钩子与Vue2有所不同,它们以onXXX
函数的形式提供,可以在setup
函数中使用。Vue2.7也实现了这些钩子函数,让我们深入了解其实现原理。
生命周期钩子的创建
Vue2.7中的生命周期钩子是通过createLifeCycle
函数创建的:
function createLifeCycle(hookName) {
return (fn, target = currentInstance) => {
if (!target) {
__DEV__ &&
warn(
`${formatName(hookName)} is called when there is no active component instance to be ` +
`associated with. ` +
`Lifecycle injection APIs can only be used during execution of setup().`
)
return
}
return injectHook(target, hookName, fn)
}
}
function formatName(name) {
if (name === 'beforeDestroy') {
name = 'beforeUnmount'
} else if (name === 'destroyed') {
name = 'unmounted'
}
return `on${name[0].toUpperCase() + name.slice(1)}`
}
function injectHook(instance, hookName, fn) {
const options = instance.$options
options[hookName] = mergeLifecycleHook(options[hookName], fn)
}
这段代码展示了生命周期钩子的创建过程:
createLifeCycle
返回一个函数,接受钩子函数和目标组件实例- 检查是否有当前实例(确保在setup中调用)
- 通过
injectHook
将钩子函数注入到组件选项中 mergeLifecycleHook
确保多个相同类型的钩子都能被调用
生命周期钩子的定义
export const onBeforeMount = createLifeCycle('beforeMount')
export const onMounted = createLifeCycle('mounted')
export const onBeforeUpdate = createLifeCycle('beforeUpdate')
export const onUpdated = createLifeCycle('updated')
export const onBeforeUnmount = createLifeCycle('beforeDestroy')
export const onUnmounted = createLifeCycle('destroyed')
export const onActivated = createLifeCycle('activated')
export const onDeactivated = createLifeCycle('deactivated')
export const onServerPrefetch = createLifeCycle('serverPrefetch')
注意onBeforeUnmount
和onUnmounted
内部使用的是Vue2的钩子名称('beforeDestroy'和'destroyed'),但对外提供了Vue3风格的API。
生命周期钩子的执行顺序
组件生命周期钩子的执行顺序是从父组件到子组件,然后再从子组件到父组件:
// 挂载阶段
parent beforeMount -> child beforeMount -> child mounted -> parent mounted
// 更新阶段
parent beforeUpdate -> child beforeUpdate -> child updated -> parent updated
// 卸载阶段
parent beforeUnmount -> child beforeUnmount -> child unmounted -> parent unmounted
这种执行顺序确保了子组件在父组件的上下文中正确初始化和销毁。
调试钩子
Vue3还引入了两个用于调试的钩子:
export const onRenderTracked = createLifeCycle<(e: DebuggerEvent) => any>('renderTracked')
export const onRenderTriggered = createLifeCycle<(e: DebuggerEvent) => any>('renderTriggered')
这些钩子可以帮助我们追踪组件渲染的依赖关系和触发原因。
总结
Vue2.7中的生命周期钩子实现了与Vue3相同的API,但内部仍然使用Vue2的生命周期机制。理解这些钩子的实现原理,有助于我们在正确的时机执行代码,避免常见的生命周期相关问题。组合式API中的生命周期钩子提供了更灵活的方式来组织组件逻辑,使代码更加模块化和可维护。