一、什么是Vue生命周期?
Vue生命周期是指Vue实例(或组件)从创建到销毁的整个过程,这个过程中Vue会在特定阶段自动调用一些特殊的函数,这些函数被称为生命周期钩子函数(Lifecycle Hooks)。生命周期钩子函数使开发者能够在组件的不同阶段执行特定的操作,从而更好地控制组件的行为和状态。
生命周期的重要性
理解Vue生命周期对于前端开发至关重要,原因如下:
- 精准控制:在合适的时机执行数据初始化、DOM操作、资源清理等操作
- 性能优化:避免在不必要的阶段执行耗时操作,提升应用性能
- 内存管理:在组件销毁时正确释放资源,防止内存泄漏
- 代码组织:使代码逻辑更加清晰,便于维护和调试
二、Vue生命周期的主要阶段
Vue生命周期可以分为四个主要阶段,每个阶段包含两个钩子函数:
1. 创建阶段(Initialization)
创建阶段是组件实例从无到有的过程,主要完成数据观测、事件配置等初始化工作。
beforeCreate
- 触发时机:实例初始化之后,数据观测和事件配置之前
- 特点:此时无法访问data、methods中的数据和方法,$el属性不存在
- 应用场景:极少使用,可用于初始化非响应式数据或插件初始化
created
- 触发时机:实例创建完成后立即调用
- 特点:已完成数据观测、属性和方法的运算,watch/event事件回调已准备就绪,但DOM尚未挂载($el不可用)
- 应用场景:发起异步请求获取数据、初始化非DOM相关状态、绑定自定义事件
2. 挂载阶段(Mounting)
挂载阶段是组件与DOM结合的过程,将编译后的模板挂载到页面中。
beforeMount
- 触发时机:挂载开始之前,模板已编译完成,虚拟DOM已创建
- 特点:$el属性存在但内容仍为原始模板,数据未渲染到页面
- 应用场景:极少使用,可用于服务端渲染(SSR)中获取数据
mounted
- 触发时机:实例挂载到DOM后调用
- 特点:DOM已完全渲染,可通过$el或原生DOM API操作DOM元素
- 应用场景:操作DOM(初始化第三方库、图表、地图)、监听DOM事件、获取DOM尺寸
3. 更新阶段(Updating)
当组件的响应式数据发生变化时,会进入更新阶段,触发重新渲染。
beforeUpdate
- 触发时机:数据更新后,虚拟DOM重新渲染之前
- 特点:数据已更新但DOM尚未重新渲染,页面显示旧数据
- 应用场景:获取更新前的DOM状态(如滚动位置、输入框光标位置)
updated
- 触发时机:数据更新导致DOM重新渲染并打补丁后
- 特点:数据和DOM均已更新,可获取最新的DOM状态
- 注意事项:避免在此阶段修改数据,可能导致无限循环更新
- 应用场景:基于最新DOM状态执行操作、同步第三方插件数据
4. 销毁阶段(Unmounting)
当组件被销毁时,进入销毁阶段,用于清理资源,防止内存泄漏。
beforeDestroy(Vue2)/ beforeUnmount(Vue3)
- 触发时机:实例销毁之前调用
- 特点:实例仍然完全可用,可访问所有资源
- 应用场景:清除定时器、取消事件监听、解绑自定义事件、取消未完成的请求
destroyed(Vue2)/ unmounted(Vue3)
- 触发时机:实例销毁后调用
- 特点:组件及其子组件已被完全销毁,所有事件监听器被移除
- 应用场景:确认资源已释放、记录销毁日志
三、Vue2与Vue3生命周期对比
Vue3在生命周期方面进行了优化和改进,主要变化如下:
钩子函数名称变化
| Vue2钩子函数 | Vue3钩子函数 | 说明 |
|---|---|---|
| beforeDestroy | beforeUnmount | 语义更准确,明确对应卸载阶段 |
| destroyed | unmounted | 命名更清晰,表示组件已卸载 |
Composition API的引入
Vue3引入了组合式API(Composition API),生命周期钩子使用方式发生变化:
Vue2选项式API
export default {
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
mounted() {
console.log('mounted')
}
}
Vue3组合式API
import { onMounted, onUpdated, onUnmounted } from 'vue'
export default {
setup() {
onMounted(() => {
console.log('组件已挂载')
})
onUpdated(() => {
console.log('组件已更新')
})
onUnmounted(() => {
console.log('组件即将销毁')
})
}
}
新增调试钩子
Vue3新增了两个调试专用的生命周期钩子:
onRenderTracked
- 作用:跟踪组件渲染依赖,在首次渲染和后续更新时触发
- 应用场景:调试组件渲染性能,分析依赖变化
onRenderTriggered
- 作用:追踪重新渲染的触发原因,仅在更新时触发
- 应用场景:分析组件重新渲染的原因,进行性能优化
执行时机差异
在Vue3中,setup()函数的执行时机相当于Vue2的beforeCreate和created之间,因此Vue3组合式API中不再需要单独使用beforeCreate和created钩子,相关逻辑可直接写在setup()函数中。
四、生命周期钩子的执行顺序
单组件执行顺序
单个组件的生命周期钩子按以下顺序执行:
beforeCreate → created → beforeMount → mounted → beforeUpdate → updated → beforeDestroy → destroyed
父子组件执行顺序
当存在父子组件关系时,生命周期钩子的执行顺序如下:
初始化阶段
父beforeCreate → 父created → 父beforeMount → 子beforeCreate → 子created → 子beforeMount → 子mounted → 父mounted
更新阶段
父beforeUpdate → 子beforeUpdate → 子updated → 父updated
销毁阶段
父beforeDestroy → 子beforeDestroy → 子destroyed → 父destroyed
五、生命周期钩子的实际应用场景
1. 数据请求的最佳时机
created阶段
export default {
data() {
return {
list: []
}
},
created() {
// 发起异步请求获取数据
axios.get('/api/data')
.then(response => {
this.list = response.data
})
}
}
mounted阶段
export default {
data() {
return {
chart: null
}
},
mounted() {
// 初始化第三方图表库
this.chart = new Chart(this.$refs.chart, {
type: 'line',
data: {
labels: ['1月', '2月'],
datasets: [{
data: [10, 20]
}]
}
})
}
}
2. 事件监听与定时器管理
export default {
data() {
return {
timer: null
}
},
mounted() {
// 绑定事件监听
window.addEventListener('resize', this.handleResize)
// 启动定时器
this.timer = setInterval(() => {
console.log('定时器执行中...')
}, 1000)
},
beforeDestroy() {
// 移除事件监听
window.removeEventListener('resize', this.handleResize)
// 清除定时器
clearInterval(this.timer)
},
methods: {
handleResize() {
// 处理窗口大小变化
}
}
}
3. DOM操作与第三方库集成
export default {
mounted() {
// 操作DOM元素
const element = document.getElementById('my-element')
element.style.color = 'red'
// 使用$nextTick确保DOM更新后执行
this.$nextTick(() => {
// 在DOM更新后执行操作
this.updateLayout()
})
},
updated() {
// 数据更新后重新渲染图表
if (this.chart) {
this.chart.update()
}
}
}
六、特殊场景的生命周期钩子
1. keep-alive组件的生命周期
当组件被<keep-alive>缓存时,会触发额外的生命周期钩子:
activated
- 触发时机:被缓存的组件激活时调用
- 应用场景:组件激活时重新获取数据、恢复状态
deactivated
- 触发时机:被缓存的组件停用时调用
- 应用场景:组件停用时暂停操作、清理临时状态
2. 错误捕获钩子
errorCaptured
- 触发时机:捕获子孙组件错误时调用
- 应用场景:全局错误处理、阻止错误向上传播
- 返回值:返回false可阻止错误继续向上传播
七、常见问题与注意事项
1. 避免在updated中修改数据
export default {
updated() {
// ❌ 错误:可能导致无限循环
this.count++
// ✅ 正确:使用计算属性或watch替代
if (this.count > 10) {
this.count = 0
}
}
}
2. 异步操作的生命周期问题
export default {
mounted() {
// 异步操作可能在组件销毁后执行
setTimeout(() => {
// 需要检查组件是否已销毁
if (this._isDestroyed) return
this.doSomething()
}, 1000)
},
beforeDestroy() {
this._isDestroyed = true
}
}
3. 服务端渲染(SSR)的特殊处理
在服务端渲染环境中,mounted钩子不会执行,因为不存在浏览器环境下的DOM操作。如果需要在服务端和客户端都执行某些逻辑,应使用created钩子。
4. 组合式API的生命周期注册
Vue3组合式API的生命周期钩子必须在setup()函数中同步注册,异步注册会导致组件实例丢失:
import { onMounted } from 'vue'
export default {
setup() {
// ✅ 正确:同步注册
onMounted(() => {
console.log('mounted')
})
// ❌ 错误:异步注册无效
setTimeout(() => {
onMounted(() => {
console.log('不会执行')
})
}, 100)
}
}
八、性能优化建议
1. 合理使用生命周期钩子
- 数据请求:在created中发起异步请求,比mounted更早执行
- DOM操作:在mounted中操作DOM,避免在created中访问$el
- 资源清理:在beforeDestroy中清除定时器、事件监听,防止内存泄漏
2. 避免不必要的重新渲染
使用v-once指令或shouldComponentUpdate(Vue3的renderTracked)来优化不必要的重新渲染:
import { onRenderTracked } from 'vue'
export default {
setup() {
onRenderTracked((event) => {
console.log('依赖变化:', event)
})
}
}
3. 使用keep-alive缓存组件
对于频繁切换的组件,使用<keep-alive>缓存组件状态,避免重复创建和销毁:
<keep-alive>
<component :is="currentComponent"></component>
</keep-alive>
九、总结
Vue生命周期是Vue框架的核心机制之一,它提供了从组件创建到销毁的完整控制能力。通过合理使用生命周期钩子函数,开发者可以在不同阶段执行特定的操作,实现数据初始化、DOM操作、资源清理等功能。
关键要点回顾:
- Vue生命周期分为创建、挂载、更新、销毁四个阶段,共8个核心钩子函数
- Vue3在生命周期方面进行了优化,引入了组合式API和新的钩子命名
- 父子组件的生命周期执行顺序遵循”父先子后,子先父后”的原则
- 合理使用生命周期钩子可以提升应用性能和代码质量
- 注意避免在updated中修改数据导致无限循环,及时在beforeDestroy中清理资源
掌握Vue生命周期是成为优秀Vue开发者的必备技能,它不仅能帮助你更好地控制组件行为,还能提升应用的性能和用户体验。
若内容若侵犯到您的权益,请发送邮件至:platform_service@jienda.com我们将第一时间处理!
所有资源仅限于参考和学习,版权归JienDa作者所有,更多请访问JienDa首页。





