[特殊字符] Vue 3 中 Keep-Alive 对生命周期的影响:深度解析

🔄 Vue 3 中 Keep-Alive 对生命周期的影响:深度解析

在 Vue 开发中,性能优化是一个永恒的话题。当我们使用 <keep-alive> 包裹组件时,组件会被缓存而不是销毁。这虽然提升了性能,但也改变了组件的生命周期行为。

很多开发者会遇到这样的困惑:

"为什么我切换标签页后,onMounted 不再执行了?"

"为什么我在 onUnmounted里清理定时器,结果定时器还在跑?"

本文将带你揭开 keep-alive 的神秘面纱,掌握新增的两个关键生命周期钩子:activated 和 deactivated。

📂 目录

  1. [核心概念:什么是 Keep-Alive?](#核心概念:什么是 Keep-Alive?)
  2. [生命周期对比:普通组件 vs 缓存组件](#生命周期对比:普通组件 vs 缓存组件)
  3. [新增钩子:Activated & Deactivated](#新增钩子:Activated & Deactivated)
  4. 实战演示:代码与现象
  5. [⚠️ 常见坑点与最佳实践](#⚠️ 常见坑点与最佳实践)
  6. [💡 总结](#💡 总结)

1. 核心概念:什么是 Keep-Alive?

<keep-alive> 是 Vue 内置的一个抽象组件,它不会渲染成 DOM 元素,也不会出现在父组件链中。

它的作用:

  • 缓存不活动的组件实例,而不是销毁它们。
  • 当组件再次被切换回来时,直接从缓存中读取,跳过创建和挂载过程。

典型场景:

  • 标签页切换(如:首页、列表页、详情页)。
  • 表单填写中途切换,希望保留用户输入的内容。
vue 复制代码
<template>
  <keep-alive>
    <component :is="currentComponent" />
  </keep-alive>
</template>

2. 生命周期对比:普通组件 vs 缓存组件

理解 keep-alive 的关键,在于对比首次进入 、切换离开 、再次进入这三个阶段的生命周期变化。

📊 生命周期流程图

阶段 普通组件 (无 Keep-Alive) 缓存组件 (有 Keep-Alive) 说明
首次渲染 beforeCreate -> created -> beforeMount-> mounted beforeCreate -> created -> beforeMount-> mounted -> activated 首次进入时,activated 会在 mounted 之后触发。
切换离开 beforeUnmount -> unmounted deactivated 关键点! 组件不会被销毁,而是触发 deactivated。
再次进入 beforeCreate -> ... -> mounted (重新创建) activated 关键点! 直接从缓存恢复,只触发 activated,不触发 mounted

🔑 核心结论:

  • 被 keep-alive 缓存的组件,onMounted 和 onUnmounted 只会执行一次(分别在第一次创建和最终真正销毁时)。
  • 后续的切换,只会触发 onActivated 和 onDeactivated。

3. 新增钩子:Activated & Deactivated

Vue 3 Composition API 中提供了两个新的生命周期钩子来处理缓存组件的状态:

✅ onActivated

  • 触发时机:组件被从缓存中激活(显示)时。
  • 用途 :
    • 重新获取最新数据(如果数据需要实时性)。
    • 重新启动定时器、动画或监听器。
    • 滚动位置恢复。

✅ onDeactivated

  • 触发时机:组件被缓存(隐藏)时。
  • 用途 :
    • 暂停定时器、视频播放、音频播放。
    • 取消不必要的网络请求。
    • 保存临时状态。

4. 实战演示:代码与现象

让我们通过一个具体的例子来观察生命周期的执行顺序。

子组件 (CachedComponent.vue)

vue 复制代码
<template>
  <div class="box">
    <h3>当前计数: {{ count }}</h3>
    <button @click="count++">增加</button>
    <p>日志: {{ logs.join(" -> ") }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, onActivated, onDeactivated } from "vue";

const count = ref(0);
const logs = ref([]);

const addLog = (msg) => {
  logs.value.push(msg);
  console.log(msg);
};

// 1. 初始化阶段
onMounted(() => {
  addLog("onMounted");
});

// 2. 激活阶段(首次进入 & 再次进入)
onActivated(() => {
  addLog("onActivated");
});

// 3. 停用阶段(切换离开)
onDeactivated(() => {
  addLog("onDeactivated");
});

// 4. 销毁阶段(只有当 keep-alive 排除该组件或父组件销毁时才触发)
onUnmounted(() => {
  addLog("onUnmounted");
});
</script>

父组件 (App.vue)

vue 复制代码
<template>
  <div>
    <button @click="toggle">切换组件</button>
    <keep-alive>
      <CachedComponent v-if="show" />
    </keep-alive>
  </div>
</template>

<script setup>
import { ref } from "vue";
import CachedComponent from "./CachedComponent.vue";

const show = ref(true);

const toggle = () => {
  show.value = !show.value;
};
</script>

🎬 现象观察

  1. 首次加载:

    • 控制台输出:onMounted -> onActivated
    • 页面显示:计数为 0。
  2. 点击"切换组件"隐藏再显示:

    • 控制台输出:onDeactivated (隐藏时) -> onActivated (显示时)
    • 注意 :onMounted 没有再次执行!
    • 页面显示:计数保持之前的值(例如你之前加到了 5,现在还是 5),证明组件状态被保留了。
  3. 最终销毁(如关闭标签页或移除 keep-alive):

    • 控制台输出:onDeactivated -> onUnmounted

⚠️ 常见坑点与最佳实践

❌ 坑点 1:在 onMounted 中请求数据,导致数据不更新

问题 :如果你只在 onMounted 中调用 API 获取列表数据,当用户从详情页返回列表页时,由于 onMounted 不执行,列表数据不会刷新,可能显示旧数据。

✅ 解决方案:

  • 将数据请求逻辑放入 onActivated。
  • 或者在 onActivated 中判断是否需要刷新。
javascript 复制代码
onActivated(() => {
  fetchData(); // 每次激活都重新获取最新数据
});

❌ 坑点 2:定时器/监听器未在 onDeactivated 中清理

问题 :在 onMounted 中启动了 setInterval 或 window.addEventListener,但在 onUnmounted 中清理。由于组件被缓存时不会触发 onUnmounted,导致定时器在后台继续运行,造成内存泄漏或性能问题。

✅ 解决方案:

  • 在 onDeactivated 中暂停或清理资源。
  • 在 onActivated 中重新启动。
javascript 复制代码
let timer = null;

onActivated(() => {
  timer = setInterval(() => {
    console.log("tick");
  }, 1000);
});

onDeactivated(() => {
  if (timer) clearInterval(timer);
});

❌ 坑点 3:误以为 keep-alive 会缓存所有状态

注意 :keep-alive 缓存的是组件实例 。如果组件内部使用了非响应式变量(如普通 let 变量),或者依赖外部全局状态但未正确订阅,可能会出现预期外的行为。务必确保状态管理的一致性。


💡 总结

特性 普通组件 Keep-Alive 组件
创建/挂载 每次切换都执行 仅首次执行
销毁/卸载 每次切换都执行 仅最终移除时执行
激活/停用 无 onActivated / onDeactivated
状态保留 不保留 保留 (包括 data, computed, DOM 状态)
适用场景 一次性页面、简单组件 标签页、表单、高频切换列表

🚀 最佳实践口诀:

缓存组件要记牢,Mounted 只跑第一遭。

数据刷新找 Activated,资源清理 Deactivated 跑。

定时器、监听器,切换隐藏记得消。

希望这篇文档能帮你彻底搞定 Vue 3 中的 keep-alive 生命周期!如果有疑问,欢迎留言交流。👇

觉得有用吗?点赞、收藏、关注,获取更多 Vue 进阶干货! ❤️

相关推荐
涛涛ing16 分钟前
Navigation API正式Baseline:那个让无数前端头疼的History API,终于可以退休了
前端
Hilaku22 分钟前
为什么我劝应届生不要去创业公司写前端?
前端·javascript·程序员
郑州光合科技余经理25 分钟前
出海外卖平台:支付对接为什么要和下单收款分开
android·java·开发语言·前端·后端·php·ai编程
data analyse 45640 分钟前
前端自建访问统计,访客标识怎么设计才稳?Cookie、本地存储与设备指纹的取舍
前端·数据分析
终端安全笔记1 小时前
配置锁状态那一栏查的是什么:报告里几项各自指向什么风险
android·前端·安全·ios
恋猫de小郭1 小时前
Kotlin Toolchain 0.13,JetBrains 推荐 KMP 都切换到到全新工具链
android·前端·flutter
高级程序源1 小时前
hive电商平台商品销售数据分析与趋势预测45659-计算机课程设计、毕业设计
vue.js·hive·spring boot·mysql·数据分析·django·课程设计
我是人✓1 小时前
Java面向对象核心特性深度解析
java·前端·算法
晓得迷路了1 小时前
栗子前端技术周刊第 149 期 - Vite+ 1.0、Preact 11、Next.js 16.4...
前端·javascript·react.js
IT_陈寒1 小时前
为什么我的Vue组件总是莫名其妙更新?
前端·人工智能·后端