Vue 3 的发布带来了全新的组合式 API,不仅改变了代码组织方式,也重新设计了生命周期钩子的使用形式。对于从 Vue 2 迁移过来的开发者,理解生命周期钩子在选项式 API 与组合式 API 中的差异,是掌握 Vue 3 的关键一步。本文将系统梳理 Vue 3 中的生命周期钩子,对比两种 API 风格的写法、执行时机与适用场景,并给出迁移建议与最佳实践。
一、Vue 3 生命周期钩子概览
无论使用哪种 API 风格,Vue 3 组件实例的生命周期都包含以下主要阶段:
- 创建阶段:
beforeCreate、created - 挂载阶段:
beforeMount、mounted - 更新阶段:
beforeUpdate、updated - 卸载阶段:
beforeUnmount、unmounted - 错误处理:
errorCaptured - 其他:
activated、deactivated(KeepAlive 缓存组件)、renderTracked、renderTriggered(开发调试)
与 Vue 2 相比,Vue 3 将 beforeDestroy 和 destroyed 重命名为 beforeUnmount 和 unmounted,语义更准确。同时,组合式 API 中新增了 onRenderTracked 和 onRenderTriggered 两个调试钩子。
二、选项式 API 中的生命周期钩子
选项式 API 延续了 Vue 2 的写法,将生命周期钩子作为组件选项直接定义:
export default {
data() {
return { count: 0 }
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log('mounted')
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeUnmount() {
console.log('beforeUnmount')
},
unmounted() {
console.log('unmounted')
}
}
选项式 API 的优点是直观、易于理解,所有钩子都平铺在组件选项中,适合小型组件或初学者。但缺点是逻辑分散:同一个功能相关的代码可能被拆分到 data、methods、mounted 等多个选项中,导致组件难以维护。
三、组合式 API 中的生命周期钩子
组合式 API 通过 setup 函数或 <script setup> 语法糖使用生命周期钩子。所有钩子都需要从 vue 中显式导入,并以 on 开头:
import {
onBeforeMount,
onMounted,
onBeforeUpdate,
onUpdated,
onBeforeUnmount,
onUnmounted
} from 'vue'
export default {
setup() {
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate')
})
onUpdated(() => {
console.log('onUpdated')
})
onBeforeUnmount(() => {
console.log('onBeforeUnmount')
})
onUnmounted(() => {
console.log('onUnmounted')
})
}
}
在 <script setup> 中写法更简洁:
<script setup>
import { onMounted, onUnmounted } from 'vue'
onMounted(() => {
console.log('组件已挂载')
})
onUnmounted(() => {
console.log('组件已卸载')
})
</script>
组合式 API 的对应关系
| 选项式 API | 组合式 API |
|---|---|
| beforeCreate | 不需要,直接写在 setup 中 |
| created | 不需要,直接写在 setup 中 |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeUnmount | onBeforeUnmount |
| unmounted | onUnmounted |
| errorCaptured | onErrorCaptured |
| activated | onActivated |
| deactivated | onDeactivated |
| renderTracked | onRenderTracked |
| renderTriggered | onRenderTriggered |
注意:beforeCreate 和 created 在组合式 API 中没有对应的钩子,因为 setup 本身就在这两个阶段之间执行,所有同步代码都相当于在这两个阶段运行。
四、核心差异对比
1. 执行时机与调用顺序
在选项式 API 中,生命周期钩子按照固定顺序执行。在组合式 API 中,钩子的注册顺序决定了执行顺序。例如,多个 onMounted 会按照注册顺序依次执行:
onMounted(() => console.log('第一个'))
onMounted(() => console.log('第二个'))
// 输出:第一个、第二个
此外,组合式 API 中如果使用了多个 setup(如混入),钩子的执行顺序也遵循注册顺序,而非选项式 API 中的合并策略。
2. 代码组织与逻辑复用
组合式 API 最大的优势是逻辑复用。通过自定义组合函数,可以将相关的生命周期逻辑封装在一起:
// useMouse.js
import { ref, onMounted, onUnmounted } from 'vue'
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
return { x, y }
}
在组件中使用:
<script setup>
import { useMouse } from './useMouse'
const { x, y } = useMouse()
</script>
这种模式在选项式 API 中只能通过 mixin 实现,但 mixin 存在命名冲突、来源不清晰等问题。组合式 API 从根本上解决了这些痛点。
3. this 的访问
选项式 API 中,生命周期钩子可以通过 this 访问组件实例。组合式 API 中,setup 内没有 this,需要通过 ref 或 getCurrentInstance 访问。官方建议尽量避免使用 getCurrentInstance,而是通过组合函数显式传递依赖。
4. 异步操作的处理
在组合式 API 中,setup 可以是异步函数(需配合 <Suspense>),但生命周期钩子必须在 setup 同步执行期间注册。如果在 await 之后注册钩子,将无法正确绑定到当前组件实例。因此,推荐将异步逻辑放在 onMounted 中:
onMounted(async () => {
const data = await fetchData()
})
五、迁移建议与最佳实践
- 新项目优先使用组合式 API:尤其是
<script setup>,代码更简洁,类型推断更友好。 - 旧项目渐进迁移:选项式 API 在 Vue 3 中完全支持,可以逐步将复杂组件改写为组合式 API。
- 避免在 setup 中滥用生命周期:能用
watch、watchEffect或计算属性解决的问题,不要强行放入生命周期钩子。 - 清理副作用:在
onUnmounted中清除定时器、事件监听、订阅等,防止内存泄漏。 - 注意 SSR 兼容:
onMounted在服务端渲染中不会执行,涉及 DOM 的操作应放在onMounted中。
六、总结
Vue 3 的生命周期钩子在选项式 API 中基本保持了 Vue 2 的形态,仅将销毁相关钩子重命名;而在组合式 API 中,钩子以 on 前缀的函数形式出现,需要显式导入,并与 setup 逻辑紧密结合。组合式 API 在逻辑复用、代码组织和类型支持方面具有明显优势,是 Vue 3 推荐的开发方式。理解两种 API 的差异,有助于开发者根据项目需求灵活选择,并顺利从 Vue 2 迁移到 Vue 3。
未经允许不得转载:任鹏个人博客 » Vue 3 生命周期钩子全面解析:组合式 API 与传统选项式的差异


朋友圈点赞图在线生成源码