D31. Vue 组件化 生命周期
1.1. 🌟 Vue 组件的生命周期
组件从出生到消亡的全过程,就像一个生命体的“人生阶段”。Vue通过生命周期钩子,让我们在特定阶段执行代码,控制组件行为。
html
<template>
<div>
<h3>{{ title }}</h3>
<p>生命周期钩子示例</p>
</div>
</template>
<script setup>
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, nextTick } from 'vue';
const title = ref("Vue组件生命周期");
1.2. 🌟 生命周期钩子与关键阶段
Vue组件的生命周期分为四个阶段,每个阶段都有对应的钩子函数:
1.2.1. 创建阶段:初始化数据
- beforeCreate:在组合式API中,
setup()
执行前已完成实例创建,无法直接访问该阶段。 - created:
setup()
函数执行阶段,此时数据已初始化。
javascript
// created阶段示例(直接在setup中执行)
console.log("created: 数据已初始化", title.value); // 输出"Vue组件生命周期"
TIP
created
是发起异步请求的黄金时机,此时数据已准备就绪。
1.2.2. 挂载阶段:DOM渲染完成
- beforeMount:虚拟DOM生成但未挂载,无法操作真实DOM。
- mounted:组件挂载到DOM,此时可安全操作DOM元素。
javascript
onBeforeMount(() => {
console.log("beforeMount: DOM未挂载", document.querySelector("#app")); // 输出null
});
onMounted(() => {
console.log("mounted: DOM已挂载", document.querySelector("#app")); // 输出真实DOM节点
nextTick(() => {
// DOM更新完成后执行
console.log("DOM更新完成");
});
});
WARNING
直接在mounted
中操作DOM可能因渲染延迟导致问题,建议使用nextTick()
。
1.2.3. 更新阶段:响应数据变化
- beforeUpdate:数据变化后,虚拟DOM更新前。
- updated:DOM更新完成,但频繁操作可能导致性能问题。
javascript
onBeforeUpdate(() => {
console.log("beforeUpdate: 数据已变,DOM未更新");
});
onUpdated(() => {
console.log("updated: DOM已更新");
// 避免在此修改数据,否则可能引发无限循环
});
1.2.4. 销毁阶段:资源释放
- beforeUnmount(Vue3):组件销毁前,可清理资源。
- unmounted(Vue3):组件完全销毁。
javascript
onBeforeUnmount(() => {
console.log("beforeUnmount: 即将销毁,清理资源");
// 停止定时器、移除事件监听
clearInterval(timer.value);
});
onUnmounted(() => {
console.log("unmounted: 组件已销毁");
});
1.3. ⚠️ 生命周期最佳实践
1.3.1. 避免在更新阶段引发无限循环
javascript
// ❌ 错误示例:updated中修改数据导致无限循环
onUpdated(() => {
title.value = "新标题"; // 触发再次更新
});
TIP
若需根据数据变化执行操作,优先在watch
或计算属性中处理。
1.3.2. 安全操作DOM的时机选择
需求场景 | 推荐钩子 | 说明 |
---|---|---|
初始化数据 | setup() | 数据已就绪,无DOM依赖 |
发送AJAX请求 | setup() 或onMounted | setup() 适合无DOM操作的请求 |
操作DOM元素 | onMounted | 确保DOM已渲染 |
清理定时器/事件监听 | onBeforeUnmount | 避免内存泄漏 |
1.4. 🔄 keep-alive:组件缓存与状态保持
<keep-alive>
是Vue内置组件,可缓存组件实例,避免重复渲染和销毁。
vue
<template>
<keep-alive>
<router-view v-if="$route.meta.keepAlive"></router-view>
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"></router-view>
</template>
TIP
- 作用:保留组件状态,保留
data
和DOM。 - 钩子扩展:组件内可添加
onActivated
(激活时)和onDeactivated
(停用时)。
javascript
import { onActivated, onDeactivated } from 'vue';
onActivated(() => {
console.log("activated: 组件被激活");
});
onDeactivated(() => {
console.log("deactivated: 组件被停用");
});
1.5. 🎯 Vue 过渡系统
Vue提供开箱即用的过渡效果,通过transition
组件和CSS类名实现。
1.5.1. CSS过渡与动画
vue
<template>
<transition name="fade">
<p v-if="show">淡入淡出效果</p>
</transition>
</template>
<script setup>
const show = ref(true);
</script>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
1.5.2. 自动绑定过渡类名
Vue会自动添加以下类名:
v-enter
:进入过渡的起点(隐藏状态)v-enter-active
:进入过渡的激活状态v-leave
:离开过渡的起点v-leave-active
:离开过渡的激活状态
TIP
通过name
属性可自定义类名前缀(如fade-enter
)。
1.5.3. 与生命周期的配合使用
过渡的触发时机与生命周期钩子紧密相关:
onMounted
:首次渲染完成,可触发显示动画。onBeforeUnmount
:销毁前可控制过渡的显示/隐藏。
javascript
onMounted(() => {
show.value = true; // 触发进入动画
});
onBeforeUnmount(() => {
show.value = false; // 触发离开动画
});
知识回顾
- 生命周期阶段:创建、挂载、更新、销毁,共8个钩子。
- 关键钩子场景:
setup()
:初始化数据onMounted
:操作DOMonBeforeUnmount
:释放资源
- 过渡系统:通过
<transition>
和CSS类名实现视图变化动画。
课后练习
单选:在哪个钩子中可以安全操作DOM元素?
- A.
setup()
- B.
onBeforeMount
- C.
onMounted
- D.
onBeforeCreate
- A.
填空:
keep-alive
组件中,组件被激活时会触发______钩子。简答:为什么在
onUpdated
钩子中修改数据可能导致无限循环?
参考答案
- C
onActivated
onUpdated
在数据变化后触发,若在此修改数据会再次触发更新,形成循环。