一、生命周期概述
Vue 组件从创建到销毁的整个过程称为生命周期,在这个过程中,Vue 会自动触发一系列的函数,这些函数被称为生命周期钩子。通过生命周期钩子,我们可以在组件的不同阶段执行特定的操作,例如初始化数据、发送请求、操作 DOM 等。
Vue 3 的生命周期钩子与 Vue 2 相比,在命名和使用方式上有一些变化,同时支持选项式 API 和组合式 API 两种风格。
二、选项式 API 中的生命周期钩子
选项式 API 中的生命周期钩子以选项的形式定义在组件中,无需导入即可直接使用。
2.1 常用生命周期钩子及执行时机
- beforeCreate:在实例初始化之后、数据观测 (data observer) 和 event/watcher 事件配置之前被调用。此时组件实例的属性和方法尚未初始化,无法访问 data、methods 等。
- created:在实例创建完成后被立即调用。此时组件实例已完成数据观测、属性和方法的运算,但尚未开始 DOM 编译,即未挂载到 DOM 上,无法访问 $el。通常在此钩子中进行数据初始化、发送初始化请求等操作。
- beforeMount:在挂载开始之前被调用。此时模板已编译完成,但尚未将编译好的模板挂载到页面中,$el 属性已存在但未挂载。
- mounted:在实例挂载完成后被调用。此时组件已挂载到 DOM 上,可以访问和操作 DOM 元素,通常在此钩子中执行需要 DOM 支持的操作,如初始化第三方插件。
- beforeUpdate:在数据更新之前被调用,发生在虚拟 DOM 重新渲染和打补丁之前。可以在此时访问到更新前的 DOM 状态。
- updated:在数据更新之后被调用,此时虚拟 DOM 已重新渲染并应用了补丁,组件 DOM 已更新。应避免在此钩子中修改数据,以免陷入无限循环。
- beforeUnmount:在组件实例卸载之前调用。此时组件实例仍然完全可用,可以在这里执行一些清理操作,如清除定时器、取消事件监听等。
- unmounted:在组件实例卸载之后调用。此时组件的所有指令和事件监听器都已被移除,DOM 元素也已从页面中移除。
2.2 选项式 API 生命周期钩子使用案例
<template><div><p>{{ message }}</p><button @click="updateMessage">更新消息</button></div></template><script>export default {data() {return {message: '初始消息',timer: null}},beforeCreate() {console.log('beforeCreate 钩子执行')console.log('此时 data 中的 message:', this.message) // undefined},created() {console.log('created 钩子执行')console.log('此时 data 中的 message:', this.message) // 初始消息// 发送初始化请求示例console.log('发送初始化数据请求...')},beforeMount() {console.log('beforeMount 钩子执行')console.log('此时的 $el:', this.$el) // 已存在但未挂载},mounted() {console.log('mounted 钩子执行')console.log('此时的 $el:', this.$el) // 已挂载到 DOM// 启动定时器示例this.timer = setInterval(() => {console.log('定时器执行中...')}, 1000)},beforeUpdate() {console.log('beforeUpdate 钩子执行')console.log('更新前的 message:', this.message)},updated() {console.log('updated 钩子执行')console.log('更新后的 message:', this.message)},beforeUnmount() {console.log('beforeUnmount 钩子执行')// 清除定时器clearInterval(this.timer)console.log('定时器已清除')},unmounted() {console.log('unmounted 钩子执行')console.log('组件已卸载')},methods: {updateMessage() {this.message = '更新后的消息'}}}</script>
在上述案例中,通过在组件选项中定义各个生命周期钩子,我们可以清晰地看到每个钩子的执行时机和可执行的操作。
三、组合式 API 中的生命周期钩子
组合式 API 中的生命周期钩子需要从 vue 中导入后才能使用,且命名以 on 开头,例如 onMounted、onUpdated 等。
3.1 常用生命周期钩子及对应关系
组合式 API 中的生命周期钩子与选项式 API 中的钩子一一对应,具体对应关系如下:
- onBeforeMount:对应选项式 API 的 beforeMount
- onMounted:对应选项式 API 的 mounted
- onBeforeUpdate:对应选项式 API 的 beforeUpdate
- onUpdated:对应选项式 API 的 updated
- onBeforeUnmount:对应选项式 API 的 beforeUnmount
- onUnmounted:对应选项式 API 的 unmounted
此外,组合式 API 中没有直接对应 beforeCreate 和 created 的钩子,因为在 setup 函数中,代码的执行时机介于 beforeCreate 和 created 之间,因此可以将原本在 beforeCreate 和 created 中执行的操作直接写在 setup 函数中。
3.2 组合式 API 生命周期钩子使用案例
<template><div><p>{{ count }}</p><button @click="count++">增加计数</button></div></template><script setup>import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'const count = ref(0)let timer = null// 相当于 beforeCreate 和 created 钩子console.log('setup 中执行(相当于 beforeCreate 和 created)')console.log('count 的初始值:', count.value)onBeforeMount(() => {console.log('onBeforeMount 钩子执行')})onMounted(() => {console.log('onMounted 钩子执行')// 启动定时器timer = setInterval(() => {count.value++}, 2000)})onBeforeUpdate(() => {console.log('onBeforeUpdate 钩子执行,更新前的 count:', count.value)})onUpdated(() => {console.log('onUpdated 钩子执行,更新后的 count:', count.value)})onBeforeUnmount(() => {console.log('onBeforeUnmount 钩子执行')// 清除定时器clearInterval(timer)console.log('定时器已清除')})onUnmounted(() => {console.log('onUnmounted 钩子执行')})</script>
在组合式 API 中,生命周期钩子以函数的形式使用,需要先导入再调用,每个钩子函数接收一个回调函数,回调函数中包含该钩子需要执行的操作。
四、生命周期钩子的实际应用场景
- 数据初始化:在 created(选项式)或 setup(组合式)中初始化组件所需的数据,例如从本地存储中读取数据。
- 发送请求:在 created 或 mounted 中发送异步请求获取后端数据,mounted 中可以结合 DOM 操作处理请求结果。
- 初始化插件:在 mounted 中初始化需要 DOM 支持的第三方插件,如图表插件、富文本编辑器等。
- 监听事件:在 mounted 中为 DOM 元素添加事件监听器,在 beforeUnmount 中移除监听器,避免内存泄漏。
- 清理操作:在 beforeUnmount 中清除定时器、取消未完成的请求、解绑自定义事件等,确保组件卸载后不会留下副作用。
五、选项式 API 与组合式 API 生命周期对比
选项式 API 钩子 | 组合式 API 钩子 | 执行时机 |
beforeCreate | - | 组件实例初始化前 |
created | - | 组件实例创建后 |
beforeMount | onBeforeMount | 组件挂载前 |
mounted | onMounted | 组件挂载后 |
beforeUpdate | onBeforeUpdate | 数据更新前 |
updated | onUpdated | 数据更新后 |
beforeUnmount | onBeforeUnmount | 组件卸载前 |
unmounted | onUnmounted | 组件卸载后 |
通过对比可以看出,组合式 API 中的生命周期钩子与选项式 API 中的钩子功能一致,只是命名和使用方式不同。在实际开发中,可根据项目风格和个人习惯选择合适的 API 风格。
结语:
接下来我会讲解 Vue 3 中组件通信的更多方式,除了之前提到的父传子,还会介绍子传父、兄弟组件通信以及跨级组件通信等,并结合案例说明每种方式的实现方法和适用场景。