1. 从Vue2到Vue3的生命周期变革
十年前我第一次接触Vue2时,被它清晰的生命周期钩子所吸引。这些钩子就像一本操作手册,告诉我组件在不同阶段应该做什么。但随着项目复杂度提升,Vue2的生命周期开始暴露出一些问题:逻辑分散、难以复用、类型支持弱等。直到Vue3推出全新的Composition API,生命周期钩子迎来了革命性的进化。
Vue3保留了大部分Vue2的生命周期概念,但在使用方式和内部实现上做了重大调整。最直观的变化是钩子函数的命名:除了created被移除外,其他钩子都加上了"on"前缀,比如mounted变成了onMounted。这不仅是命名规范的变化,更代表着组合式API的思想转变——生命周期钩子现在可以像普通函数一样被灵活调用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Vue2生命周期全解析
2.1 传统选项式API的生命周期
在Vue2中,生命周期钩子作为组件选项直接定义在对象中:
javascript复制export default {
data() {
return { count: 0 }
},
created() {
console.log('实例创建完成')
},
mounted() {
console.log('DOM挂载完成')
}
}
完整的Vue2生命周期包含8个主要钩子:
beforeCreate- 实例初始化后,数据观测(data observer)和事件配置之前created- 实例创建完成,已配置数据观测,但尚未挂载DOMbeforeMount- 模板编译/挂载之前mounted- 实例挂载到DOM后调用beforeUpdate- 数据更新时,虚拟DOM重新渲染和打补丁之前updated- 数据更改导致虚拟DOM重新渲染后beforeDestroy- 实例销毁之前destroyed- 实例销毁后
2.2 Vue2生命周期的典型问题
在实际项目中,Vue2的生命周期存在几个明显痛点:
-
逻辑关注点分离:相关代码被分散在不同钩子中。比如一个定时器,需要在
mounted中启动,在beforeDestroy中清除,两者可能相隔数百行代码。 -
代码复用困难:相似的逻辑需要在多个组件中重复编写生命周期代码,即使使用mixins也存在命名冲突等问题。
-
类型支持有限:在TypeScript项目中,Vue2的选项式API类型推断不够友好。
javascript复制// Vue2中分散的生命周期代码
export default {
data() {
return { timer: null }
},
mounted() {
this.timer = setInterval(() => {
// 业务逻辑
}, 1000)
},
beforeDestroy() {
clearInterval(this.timer)
}
}
3. Vue3生命周期革命
3.1 Composition API带来的变革
Vue3引入的Composition API彻底改变了生命周期的使用方式。现在,生命周期钩子可以作为函数在setup()中调用:
javascript复制import { onMounted, onUnmounted } from 'vue'
export default {
setup() {
const timer = ref(null)
onMounted(() => {
timer.value = setInterval(() => {
// 业务逻辑
}, 1000)
})
onUnmounted(() => {
clearInterval(timer.value)
})
}
}
Vue3的生命周期钩子函数列表:
| Vue2钩子 | Vue3对应钩子 | 变化说明 |
|---|---|---|
| beforeCreate | 无 | 被setup()取代 |
| created | 无 | 被setup()取代 |
| beforeMount | onBeforeMount | 添加on前缀 |
| mounted | onMounted | 添加on前缀 |
| beforeUpdate | onBeforeUpdate | 添加on前缀 |
| updated | onUpdated | 添加on前缀 |
| beforeDestroy | onBeforeUnmount | 更名+添加on前缀 |
| destroyed | onUnmounted | 更名+添加on前缀 |
| errorCaptured | onErr |
