Vue 生命周期:深入理解组件从诞生到销毁的全过程
在 Vue 开发中,生命周期是组件从创建、挂载、更新到销毁的完整过程。每个阶段都有对应的钩子函数,让开发者能在特定时机执行代码。深入理解生命周期是掌握 Vue 的核心关键。
一、生命周期四大阶段
1. 创建阶段(Initialization)
-
beforeCreate组件实例刚创建,数据观测和事件机制尚未初始化beforeCreate() { console.log(this.message) // undefined console.log(this.$el) // undefined } -
created实例创建完成,已完成数据观测,属性和方法的运算,可访问数据和方法(最常用的异步请求时机),但尚未挂载到 DOMcreated() { console.log(this.message) // "Hello Vue!" this.fetchData() // 发起API请求 }
2. 挂载阶段(DOM Insertion)
-
beforeMount模板编译完成,但尚未渲染到页面beforeMount() { console.log(document.getElementById('app')) // null } -
mounted实例已挂载到 DOM,可操作 DOM 元素mounted() { console.log(this.$el) // 获取DOM节点 this.initChart() // 初始化ECharts图表 }
3. 更新阶段(Re-rendering)
-
beforeUpdate在数据发生改变后,DOM 被更新之前被调用数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前export default { data() { return { count: 0 } }, methods: { increment() { this.count++; // 数据立即更新 } }, beforeUpdate() { console.log("beforeUpdate - 数据已新:", this.count); // 输出新值(如 1) console.log("DOM 内容仍是旧的:", document.getElementById("count").textContent); // 输出旧值(如 0) } }关键点:
- ✅
beforeUpdate中的数据状态: 数据确实已完成更改(组件实例的this.xxx已是新值),但 DOM 尚未更新,因此视图与数据不同步。 - ❌ 常见误解:
错误认为 "
beforeUpdate时数据还未更新",实际上数据变更发生在beforeUpdate之前。
- ✅
-
updated数据更改导致的 DOM 更新完成后updated() { // 注意:避免在此处修改状态,可能导致无限循环! console.log('DOM已更新') }
4. 销毁阶段(Teardown)
| 对比项 | Vue 2 | Vue 3 | 说明 |
|---|---|---|---|
| 钩子命名 | beforeDestroy / destroyed | beforeUnmount / unmounted | Vue 3 使用更准确的术语("unmount" 而非 "destroy")。 |
| 组合式 API 影响 | 无 | setup() 内部可使用 onBeforeUnmount 和 onUnmounted | Vue 3 的组合式 API 提供了更灵活的销毁逻辑管理方式。 |
| 异步清理 | 同步销毁 | 支持异步组件卸载(<Suspense>) | Vue 3 的异步组件卸载机制更完善。 |
| 事件监听器自动清理 | 需要手动移除 | 在 setup() 中使用 onUnmounted 自动清理 watch 和 computed | Vue 3 的组合式 API 更易于管理副作用。 |
-
beforeUnmount实例销毁前,资源清理的最佳时机beforeUnmount() { clearInterval(this.timer) // 清除定时器 window.removeEventListener('resize', this.handleResize) // 移除事件监听 } -
unmounted实例完全销毁,所有绑定和子实例被移除unmounted() { console.log('组件已销毁') }
二、特殊场景的生命周期钩子
1. keep-alive 相关
-
activated被缓存的组件激活时调用(如从后台切回前台)activated() { this.startAutoRefresh() // 重新启动轮询 } -
deactivated被缓存的组件停用时调用deactivated() { this.stopAutoRefresh() // 停止后台任务 }
2. 错误捕获
-
errorCaptured捕获子孙组件的错误(Vue 2.5+)errorCaptured(err, vm, info) { console.error(`捕获到错误: ${err.toString()}`) this.logErrorToService(err) // 上报错误日志 return false // 阻止错误继续向上传播 }
三、生命周期流程图解
创建阶段
↓
beforeCreate → created(初始化数据)
↓
挂载阶段
↓
beforeMount → mounted(操作DOM)
↓
↻ 更新循环 ↺
beforeUpdate → updated
↓
销毁阶段
↓
beforeUnmount → unmounted
四、最佳实践与常见陷阱
-
异步请求放在哪里?
- 使用
created:需要尽早获取数据时 - 使用
mounted:需要访问 DOM 时
- 使用
-
避免在 updated 中修改状态 可能导致无限更新循环,使用计算属性或侦听器替代
-
内存泄漏防范 在
beforeDestroy中必须清理:beforeUnmount() { // 清除定时器 clearTimeout(this.timer) // 移除全局事件 window.removeEventListener('scroll', this.handleScroll) // 取消未完成的异步任务 this.cancelToken && this.cancelToken.cancel() } -
父子组件生命周期顺序
父beforeCreate → 父created → 父beforeMount → 子beforeCreate → 子created → 子beforeMount → 子mounted → 父mounted
五、Vue 3 的变化
在 Vue 3 的 Composition API 中,生命周期通过 setup() 函数访问:
import { onMounted, onUpdated } from 'vue'
setup() {
onMounted(() => {
console.log('组件已挂载')
})
onUpdated(() => {
console.log('数据已更新')
})
}
注意:
beforeCreate和created被setup()替代
结语
理解 Vue 生命周期如同掌握组件的"人生轨迹",能让你:
- ✅ 精准控制异步操作时机
- ✅ 高效管理资源和内存
- ✅ 避免状态更新导致的意外行为
- ✅ 优化组件性能
通过合理运用生命周期钩子,你的 Vue 应用将获得更好的可维护性和稳定性。