Vue3 生命周期钩子详解
简介
Vue3的生命周期钩子让我们能够在组件的不同阶段执行自定义代码。与Vue2相比,Vue3的生命周期钩子在Composition API中有了新的使用方式,但整体概念保持一致。
基础知识
Vue3中的生命周期钩子可以通过两种方式使用:
- 在setup()中使用onXXX形式的生命周期钩子
- 在Options API中使用与Vue2相似的方式
Composition API中的生命周期钩子
1. setup()
import { onMounted, onUpdated, onUnmounted } from 'vue'export default {setup() {// setup 本身就是在组件创建之前执行的console.log('组件初始化')onMounted(() => {console.log('组件已挂载')})return {}}
}
2. beforeCreate 和 created
在 Composition API 中,这两个钩子被 setup() 函数本身替代。setup() 函数在组件创建之前就被调用。
3. onMounted
import { onMounted } from 'vue'export default {setup() {onMounted(() => {// DOM已经可用console.log('组件已挂载到DOM')// 可以进行DOM操作const element = document.getElementById('my-element')// 可以调用第三方库初始化initializeThirdPartyLibrary()})}
}
4. onUpdated
import { onUpdated, ref } from 'vue'export default {setup() {const count = ref(0)onUpdated(() => {// 当响应式数据更新导致组件更新后调用console.log('组件已更新')console.log('当前计数:', count.value)})return {count}}
}
5. onUnmounted
import { onUnmounted } from 'vue'export default {setup() {// 设置定时器const timer = setInterval(() => {console.log('定时器执行中')}, 1000)onUnmounted(() => {// 清理工作clearInterval(timer)console.log('组件已卸载,资源已清理')})}
}
6. onBeforeMount
import { onBeforeMount } from 'vue'export default {setup() {onBeforeMount(() => {// 组件挂载到DOM之前调用console.log('组件即将挂载')})}
}
7. onBeforeUpdate
import { onBeforeUpdate, ref } from 'vue'export default {setup() {const message = ref('Hello')onBeforeUpdate(() => {// 组件更新之前调用console.log('组件即将更新')console.log('更新前的消息:', message.value)})return {message}}
}
8. onBeforeUnmount
import { onBeforeUnmount } from 'vue'export default {setup() {onBeforeUnmount(() => {// 组件卸载之前调用console.log('组件即将卸载')})}
}
9. onErrorCaptured
import { onErrorCaptured } from 'vue'export default {setup() {onErrorCaptured((err, instance, info) => {// 捕获来自子组件的错误console.error('捕获到错误:', err)console.log('错误来源组件:', instance)console.log('错误信息:', info)// 返回false阻止错误继续向上传播return false})}
}
完整的生命周期示例
import {onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted,onErrorCaptured,ref
} from 'vue'export default {setup() {const count = ref(0)console.log('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: 组件已卸载')})onErrorCaptured((err, instance, info) => {console.log('onErrorCaptured: 捕获到错误')return false})return {count}}
}
生命周期钩子最佳实践
- 数据初始化
export default {setup() {const data = ref(null)onMounted(async () => {// 在mounted时获取初始数据try {data.value = await fetchData()} catch (error) {console.error('数据获取失败:', error)}})return {data}}
}
- 资源清理
export default {setup() {const eventHandler = () => {console.log('处理窗口调整事件')}onMounted(() => {// 添加事件监听window.addEventListener('resize', eventHandler)})onUnmounted(() => {// 移除事件监听window.removeEventListener('resize', eventHandler)})}
}
注意事项
- setup() 中没有 this
- 生命周期钩子只能在 setup() 中同步调用
- 确保在条件语句外调用生命周期钩子
- 多个同类型的生命周期钩子会按照定义顺序依次执行
调试技巧
export default {setup() {// 使用开发工具进行调试onMounted(() => {console.log('组件ID:', componentId)debugger // 可以设置断点})}
}