Skip to content

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()执行前已完成实例创建,无法直接访问该阶段。
  • createdsetup()函数执行阶段,此时数据已初始化。
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()onMountedsetup()适合无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; // 触发离开动画
});

知识回顾

  1. 生命周期阶段:创建、挂载、更新、销毁,共8个钩子。
  2. 关键钩子场景
    • setup():初始化数据
    • onMounted:操作DOM
    • onBeforeUnmount:释放资源
  3. 过渡系统:通过<transition>和CSS类名实现视图变化动画。

课后练习

  1. 单选:在哪个钩子中可以安全操作DOM元素?

    • A. setup()
    • B. onBeforeMount
    • C. onMounted
    • D. onBeforeCreate
  2. 填空keep-alive组件中,组件被激活时会触发______钩子。

  3. 简答:为什么在onUpdated钩子中修改数据可能导致无限循环?

参考答案
  1. C
  2. onActivated
  3. onUpdated在数据变化后触发,若在此修改数据会再次触发更新,形成循环。

扩展阅读

Built by Vitepress | Apache 2.0 Licensed