Vue生命周期与keep-alive实战理解

Vue 生命周期与 keep-alive:我用真实项目终于搞清楚了

"生命周期"这个词在 Vue 教程里会很早出现,但很多人学了之后还是一知半解。 因为光看文档,没有感觉。这篇文章想用真实项目代码,帮你把它们"落地"。


先说一个语言上的误导

"生命周期" 这个词,听起来像是整个项目从打开到关闭的一段大流程。

但实际上,它属于每一个组件。

正确的理解是:

每个 Vue 组件实例,都有自己的出生、挂载、更新、离开、缓存激活的过程。 这些阶段,Vue 会自动调用对应的钩子函数,给你一个"插队"的机会。


🗓️ 最常用的几个生命周期钩子

created ------ 数据准备好了,但页面还没画出来

diff 复制代码
✅ 适合做什么:
- 发起不依赖 DOM 的数据请求
- 初始化变量
- 读取 Vuex / props

mounted ------ 页面已经渲染出来了,DOM 摸得到了

diff 复制代码
✅ 适合做什么:
- 操作 $refs(真实 DOM)
- 绑定滚动、键盘、resize 事件
- 初始化第三方 JS 库(图表、播放器、WebSocket 等)

beforeDestroy / destroyed ------ 组件要销毁了

diff 复制代码
✅ 适合做什么:
- 清除定时器
- 解绑事件监听
- 关闭 WebSocket
- 释放资源

activated ------ keep-alive 缓存的页面"重新回来了"

diff 复制代码
✅ 适合做什么:
- 每次回到这个页面时,重新拉数据
- 恢复某些需要刷新的状态

deactivated ------ keep-alive 缓存的页面"离开了,但没销毁"

diff 复制代码
✅ 适合做什么:
- 暂停正在播放的音频
- 停止轮询
- 暂停实时监听

🔁 keep-alive 会改变什么

keep-alive 是 Vue 的内置组件,作用是缓存被包住的组件实例

没有 keep-alive 的情况下,离开一个页面 = 销毁这个组件。

有了 keep-alive,离开页面之后组件不一定被销毁,而是被"冷冻"起来:

复制代码
首次进入缓存页:
  created → mounted → activated

离开缓存页(不销毁):
  deactivated

再次进入缓存页:
  activated  ← 直接从这里开始,跳过了 created 和 mounted!

这就是为什么你会在缓存相关的组件里,经常看到 activated 而不是 created


🔧 用真实项目代码来拆解

根实例的 created:应用一启动就执行一次

js 复制代码
// src/main.js
new Vue({
  router,
  store,
  render: h => h(App),
  created() {
    // 这里的 created 只在"整个应用开机"时执行一次
    store.commit('businessCoulmn/setWorkDetail', '');        // 重置业务状态
    store.commit('instantMessaging/setScreenfullBut', false); // 重置 IM 全屏状态
    store.commit('siteBar/addMenu', router);                  // 注入动态菜单
  },
}).$mount('#app');

这里的 created 是根实例的生命周期,属于"整个应用开机初始化",不属于任何页面。


登录页的 created + mounted:先清状态,再做页面效果

markdown 复制代码
created:
  - 清空本地存储
  - 重置菜单和 tab
  - 清空 token

mounted:
  - 启动背景动画效果

典型用法:

  • created 适合"先把旧状态清干净"
  • mounted 适合"页面展示出来之后做的事情"

IM 页面入口:created 做初始化

markdown 复制代码
created:
  1. 拿老师的聊天账号
  2. 拿 IM 配置
  3. 初始化 TIM SDK
  4. 绑定 TIM 事件
  5. 登录 IM

为什么用 created 而不是 mounted

因为这些步骤不需要操作 DOM ,提前在 created 里做,能更快完成初始化。


IM 布局组件:mounted 初始化 WebSocket

markdown 复制代码
mounted:
  - 初始化 WebSocket 连接

beforeDestroy:
  - 关闭 WebSocket
  - 停掉轮询

mounted 之所以适合初始化 WebSocket,是因为:

  • WebSocket 有时候需要操作 DOM
  • mounted 保证页面已经渲染,更安全

beforeDestroy 负责配套的清理工作,避免资源泄漏。


ConversationList 用 activated 而不是 created,是因为......

js 复制代码
// src/components/.../ConversationList/index.vue
activated() {
  this.handleGetWechatStudentList(); // 每次"回到页面"时刷新数据
}

为什么不用 created

因为这个组件被 keep-alive 包着。

  • 第一次进来会走 created
  • 切走再切回来,created 不会重新触发
  • activated 每次回来都会触发

所以这里的逻辑是:

arduino 复制代码
created  → 第一次初始化
activated → 每次"回来"时刷新数据

这是 keep-alive 场景下非常经典的写法。


MessageWindow 用 deactivated,是因为......

js 复制代码
// src/components/.../MessageWindow/index.vue
deactivated() {
  this.handlePauseAudio(); // 离开页面时暂停音频
}

为什么不用 beforeDestroy

因为这个组件被缓存了,切走页面时不是真正销毁 ,不会触发 beforeDestroy

会触发的是 deactivated,专门处理"缓存页离开时的收尾动作"。


🔄 用一次完整流程来理解

markdown 复制代码
1. 用户打开项目
   └─ main.js 创建根实例
   └─ 根实例 created 执行(初始化菜单、重置 IM 状态)

2. 用户登录
   └─ login.vue created 清空旧数据
   └─ login.vue mounted 显示背景动画

3. 进入 IM 聊天页
   └─ instant-messaging/index.vue created 做 IM 初始化
   └─ Layout/index.vue mounted 初始化 WebSocket

4. 用户切走页面
   └─ 缓存页面 → 触发 deactivated(不销毁)
   └─ 非缓存页面 → 触发 beforeDestroy(销毁)

5. 用户切回 IM 页面
   └─ 触发 activated
   └─ ConversationList 重新拉数据

⚠️ 不要混淆的三个东西

概念 是什么
生命周期 组件的出生、挂载、更新、离开、重现的各个阶段
watch 监听某个数据变化,不是生命周期
keep-alive 缓存机制,它会改变组件的生命周期表现

keep-alive 的存在,让 deactivated / activated 有意义。

没有 keep-alive 包着的组件,这两个钩子永远不会触发。


🏁 一句话总结

arduino 复制代码
Vue 生命周期不是"整个项目统一跑一遍的流程"
而是"每个组件实例自己的阶段变化"

keep-alive 改变的是"离开"和"回来"的行为:
  - 离开时不销毁 → deactivated
  - 回来时不重建 → activated

所以:
  created / mounted    → 用于首次初始化
  activated            → 用于每次回来时刷新
  deactivated          → 用于离开时收尾
  beforeDestroy        → 用于真正销毁时清理

这是 Vue2 学习系列第四篇。

下一篇:Vue、SPA、MPA 傻傻分不清?一篇弄清楚三者的关系。

相关推荐
leoZ23122 分钟前
Claude 驱动的全栈开发:Spring Boot + Vue 的 BS 架构实践
vue.js·spring boot·架构
荒诞英雄4 小时前
从 17MB Vendor 大包到按需加载:Vite 多入口 Vue 组件库首屏优化实践
vue.js·vite
jsonbro4 小时前
手把手带你实现发布订阅模式
前端·vue.js·设计模式
Cobyte6 小时前
23.Vue Vapor 组件 attrs 的实现
前端·javascript·vue.js
斯特凡今天也很帅7 小时前
xml页面可以打开,不报错,但是显示数据的地方也不显示,我是怎么解决的
xml·vue.js
柯克七七8 小时前
给老项目加了 TypeScript,本来只想自己爽,结果全公司代码审查标准被我抬高了
前端·vue.js·typescript
自然 醒10 小时前
前端如何实现在线预览office常见文件功能?
前端·vue.js
肉肉不吃 肉11 小时前
前端调试跨域如何解决
前端·vue.js
卓怡学长11 小时前
w268基于springboot + vue 物流系统
java·数据库·vue.js·spring boot·spring·intellij-idea
迅速的自行车1 天前
从一段模板说起
前端·javascript·vue.js