Vue 中 keep-alive 组件的生命周期钩子

Vue 中 keep-alive 组件的生命周期钩子

本文来自于我关于 Vue生命周期钩子 的系列文章。欢迎阅读、点评与交流~
1、Vue 中的生命周期钩子
2、Vue 中 keep-alive 组件的生命周期钩子

1. keep-alive 组件概述

keep-alive 是 Vue 的内置组件,用于缓存不活动的组件实例,而不是销毁它们。这样可以:

  • 保留组件状态,避免重新渲染
  • 提高应用性能
  • 减少重复的 DOM 操作

2. 基本用法

vue 复制代码
<template>
  <div>
    <keep-alive>
      <component :is="currentComponent"></component>
    </keep-alive>
  </div>
</template>

3. 专门的生命周期钩子

keep-alive 包裹的组件会获得两个额外的生命周期钩子:

activated

  • 调用时机:组件被激活(从缓存中取出并插入到 DOM 中)时调用
  • 使用场景:重新获取数据、开启定时器、重新绑定事件等

deactivated

  • 调用时机:组件被停用(从 DOM 中移除并存入缓存)时调用
  • 使用场景:清除定时器、取消事件监听、释放资源等

4. 完整生命周期执行顺序

首次加载

javascript 复制代码
// 组件第一次进入时
created() → mounted() → activated()

切换到其他组件(当前组件被缓存)

javascript 复制代码
// 当前组件被离开
deactivated()

再次切换回来

javascript 复制代码
// 再次进入缓存的组件
activated()

组件被销毁(当离开路由或 keep-alive 被移除)

javascript 复制代码
// 如果是直接离开路由
deactivated() → beforeDestroy() → destroyed()

// 注意:如果组件被 keep-alive 缓存,则不会触发 beforeDestroy 和 destroyed

5. 实际示例

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

<script>
// ComponentA.vue
export default {
  name: 'ComponentA',
  data() {
    return {
      timer: null,
      count: 0
    }
  },
  
  created() {
    console.log('ComponentA created')
  },
  
  mounted() {
    console.log('ComponentA mounted')
  },
  
  activated() {
    console.log('ComponentA activated')
    // 重新开启定时器
    this.timer = setInterval(() => {
      this.count++
      console.log('定时器运行中:', this.count)
    }, 1000)
  },
  
  deactivated() {
    console.log('ComponentA deactivated')
    // 清除定时器
    if (this.timer) {
      clearInterval(this.timer)
      this.timer = null
    }
  },
  
  beforeDestroy() {
    console.log('ComponentA beforeDestroy')
  },
  
  destroyed() {
    console.log('ComponentA destroyed')
  }
}
</script>

6. keep-alive 的属性配置

vue 复制代码
<!-- 只缓存特定组件 -->
<keep-alive include="ComponentA,ComponentB">
  <component :is="currentComponent"></component>
</keep-alive>

<!-- 排除某些组件 -->
<keep-alive exclude="ComponentC">
  <component :is="currentComponent"></component>
</keep-alive>

<!-- 使用正则表达式 -->
<keep-alive :include="/ComponentA|ComponentB/">
  <component :is="currentComponent"></component>
</keep-alive>

<!-- 限制最大缓存实例数 -->
<keep-alive :max="5">
  <component :is="currentComponent"></component>
</keep-alive>

7. 与 Vue Router 结合使用

javascript 复制代码
// router.js
const routes = [
  {
    path: '/page1',
    component: Page1,
    meta: {
      keepAlive: true  // 需要缓存
    }
  },
  {
    path: '/page2',
    component: Page2,
    meta: {
      keepAlive: false // 不需要缓存
    }
  }
]
vue 复制代码
<!-- App.vue -->
<template>
  <div id="app">
    <keep-alive>
      <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

8. 注意事项和最佳实践

注意事项:

  1. name 属性必需 :组件必须有 name 选项才能被 include/exclude 匹配
  2. 嵌套 keep-alive:Vue 2.2.0+ 支持嵌套使用,但应避免过度使用
  3. 动态组件 :与 <component :is="..."> 结合时最有用
  4. 内存管理 :注意内存泄漏,及时在 deactivated 中清理资源

最佳实践:

javascript 复制代码
export default {
  name: 'MyComponent', // 必须设置 name
  data() {
    return {
      // 数据会被缓存
    }
  },
  activated() {
    // 可以在这里重新获取可能需要更新的数据
    if (this.needsRefresh) {
      this.fetchData()
    }
  },
  deactivated() {
    // 清理工作
    this.cancelPendingRequests()
    clearInterval(this.timer)
  },
  methods: {
    // 如果需要刷新数据的逻辑
    fetchData() {
      // 获取数据
    },
    cancelPendingRequests() {
      // 取消未完成的请求
    }
  }
}

9. Vue 3 中的变化

在 Vue 3 中,keep-alive 的用法基本保持不变,但生命周期钩子名称有变化:

javascript 复制代码
// Vue 3 Composition API
import { onActivated, onDeactivated } from 'vue'

export default {
  setup() {
    onActivated(() => {
      console.log('组件被激活')
    })
    
    onDeactivated(() => {
      console.log('组件被停用')
    })
  }
}

总结

keep-alive 组件的生命周期钩子 activateddeactivated 为缓存组件提供了精确的控制能力。合理使用这些钩子可以有效管理组件状态、优化性能,同时避免内存泄漏等问题。在实际开发中,结合路由配置和动态组件,可以创建出体验更流畅的单页应用。

相关推荐
于慨16 小时前
Lambda 表达式、方法引用(Method Reference)语法
java·前端·servlet
石小石Orz16 小时前
油猴脚本实现生产环境加载本地qiankun子应用
前端·架构
从前慢丶16 小时前
前端交互规范(Web 端)
前端
像我这样帅的人丶你还17 小时前
别再让JS耽误你进步了。
css·vue.js
@yanyu66617 小时前
07-引入element布局及spring boot完善后端
javascript·vue.js·spring boot
CHU72903517 小时前
便捷约玩,沉浸推理:线上剧本杀APP功能版块设计详解
前端·小程序
GISer_Jing17 小时前
Page-agent MCP结构
前端·人工智能
王霸天17 小时前
💥别再抄网上的Scale缩放代码了!50行源码教你写一个永不翻车的大屏适配
前端·vue.js·数据可视化
小领航17 小时前
用 Three.js + Vue 3 打造炫酷的 3D 行政地图可视化组件
前端·github
@大迁世界17 小时前
2026年React大洗牌:React Hooks 将迎来重大升级
前端·javascript·react.js·前端框架·ecmascript