Vue3 KeepAlive缓存组件实现方式

 更新时间:2026年04月29日 14:33:21   作者:Sheldon一蓑烟雨任平生  
文章主要介绍了Vue中内置组件的使用,其中着重讲解了KeepAlive的使用方式和细节,KeepAlive用于在多个组件间动态切换时缓存被移除的组件实例,可以使用include/exclude和max属性来定制缓存行为,同时,还介绍了onActivated和onDeactivated生命周期钩子的使用方法

1. 内置组件简介

在 Vue 中也提供了一些内置组件:

  • Transition(一个元素或组件进入和离开 DOM 时应用动画)
  • TransitionGroup(对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果)
  • KeepAlive(在多个组件间动态切换时缓存被移除的组件实例)
  • Teleport(将一个组件内部的一部分模板“传送”到该组件的 DOM 结构外层的位置去)
  • Suspense(在组件树中协调对异步依赖的处理)

其中,KeepAlive 对于项目而言,最为常用,我们先进行介绍,其他内置组件,后续在添加具体的使用说明。

2. component 元素(动态组件)

component 元素,一个用于渲染动态组件或元素的“元组件”。要渲染的实际组件由 is prop 决定。

它是和 slot、template 等元素类似的一种特殊元素,这种元素是模板语法的一部分。但它们并非真正的组件,同时在模板编译期间会被编译掉。因此,它们通常在模板中用小写字母书写。

3. KeepAlive 基本使用方式

3.1 切换组件(未使用 KeepAlive,组件会销毁再重新创建)

关键代码:

<component :is="activeComponent" />




完整代码如下。

父组件 App.vue:

<template>
  <div>
    <input type="radio" v-model="activeComponent" :value="A" />
    <label for="A">A</label>
    <input type="radio" v-model="activeComponent" :value="B" />
    <label for="B">B</label>
  </div>
  <div>Current component:{{ activeComponent.__name }}</div>
  <div>
    <component :is="activeComponent" />
  </div>
</template>

<script setup>
import { shallowRef, watch } from 'vue';
import A from '@/components/A.vue';

import B from '@/components/B.vue';
const activeComponent = shallowRef(A);
watch(activeComponent, (newVal) => {
  console.log(newVal);
});
</script>

<style lang="scss" scoped>
div{
  margin-bottom: 10px;
}
</style>

子组件 A.vue:

<template>
  <div>
    <span>Count: {{ count }}</span>
    <button @click="count++">+</button>
  </div>
</template>

<script setup name="A">
import { ref } from 'vue'
const count = ref(0)
</script>

<style lang="scss" scoped>
button{
  margin-left: 10px;
}
</style>

子组件 B.vue:

<template>
  <div>
    <span>Message is: {{ message }}</span>
    <input type="text" v-model="message" />
  </div>
</template>

<script setup name="B">
import { ref } from 'vue'
const message = ref('')
</script>

<style lang="scss" scoped>
input{
  margin-left: 10px;
}
</style>

3.2 切换组件(使用 KeepAlive,组件会进行缓存)

修改 App.vue 的关键代码,外部加上一层 KeepAlive

<KeepAlive>
  <component :is="activeComponent" />
</KeepAlive>

使用 KeepAliec 后,组件间切换,组件会仍然保持之前的状态。

此时的组件切换,属于休眠/唤醒,而非销毁/创建。

3. 使用细节

3.1 包含/排除(include/exclude)

在使用 KeepAlive 时,会默认缓存内部的所有切换的组件。那如果我们只想缓存部分组件,可以通过 includeexclude prop 来定制该行为。

这两个 prop 的值都可以是一个以英文逗号分隔的字符串、一个正则表达式,或是包含这两种类型的一个数组:

<!-- 以英文逗号分隔的字符串 -->
<KeepAlive include="a,b">
  <component :is="view" />
</KeepAlive>

<!-- 正则表达式 (需使用 `v-bind`) -->
<KeepAlive :include="/a|b/">
  <component :is="view" />
</KeepAlive>

<!-- 数组 (需使用 `v-bind`) -->
<KeepAlive :include="['a', 'b']">
  <component :is="view" />
</KeepAlive>

它会根据组件的 name 选项进行匹配,所以组件如果想要条件性地被 KeepAlive 缓存,就必须显式声明一个 name 选项。

3.2.34 或以上的版本中,使用 <script setup> 的单文件组件会自动根据文件名生成对应的 name 选项,无需再手动声明。

3.2 最大缓存实例数(max)

通过传入 max prop 来限制可被缓存的最大组件实例数。

<KeepAlive> 的行为在指定了 max 后类似一个 LRU 缓存:如果缓存的实例数量即将超过指定的那个最大数量,则最久没有被访问的缓存实例将被销毁,以便为新的实例腾出空间。

<KeepAlive :max="10">
  <component :is="activeComponent" />
</KeepAlive>

3.3 缓存实例的生命周期(onActivated 和 onDeactivated)

当一个组件实例从 DOM 上移除但因为被 <KeepAlive> 缓存而仍作为组件树的一部分时,它将变为不活跃状态而不是被卸载。当一个组件实例作为缓存树的一部分插入到 DOM 中时,它将重新被激活

一个持续存在的组件可以通过 onActivated()onDeactivated() 注册相应的两个状态的生命周期钩子:

<script setup>
import { onActivated, onDeactivated } from 'vue'

onActivated(() => {
  // 调用时机为首次挂载
  // 以及每次从缓存中被重新插入时
})

onDeactivated(() => {
  // 在从 DOM 上移除、进入缓存
  // 以及组件卸载时调用
})
</script>

请注意:

  • onActivated 在组件挂载时也会调用,并且 onDeactivated 在组件卸载时也会调用。
  • 这两个钩子不仅适用于 缓存的根组件,也适用于缓存树中的后代组件。

看个例子。A组件新增一个子组件A1,B组件新增一个子组件B1。

A1.vue:

<template>
  <div>
    这是A1组件内容(A的子组件)
  </div>
</template>

<script setup>
import { onActivated, onDeactivated } from 'vue';

onActivated(() => {
  console.log('A1 onActivated')
})
onDeactivated(() => {
  console.log('A1 onDeactivated')
})
</script>

<style lang="scss" scoped>
div{
  margin-top: 10px;
}
</style>

A.vue:

<template>
  <div class="A">
    <span>Count: {{ count }}</span>
    <button @click="count++">+</button>
    <A1></A1>
  </div>
</template>

<script setup name="A">
import { ref, onActivated, onDeactivated } from 'vue';
import A1 from './A1.vue'

const count = ref(0)

onActivated(() => {
  console.log('A onActivated')
})
onDeactivated(() => {
  console.log('A onDeactivated')
})
</script>

<style lang="scss" scoped>
.A{
  border: 1px solid red;
  padding: 10px;
}
button{
  margin-left: 10px;
}
</style>

B1.vue:

<template>
  <div>
    这是B1组件内容(B的子组件)
  </div>
</template>

<script setup>
import { onActivated, onDeactivated } from 'vue';

onActivated(() => {
  console.log('B1 onActivated')
})
onDeactivated(() => {
  console.log('B1 onDeactivated')
})
</script>

<style lang="scss" scoped>
div{
  margin-top: 10px;
}
</style>

B.vue:

<template>
  <div class="B">
    <span>Message is: {{ message }}</span>
    <input type="text" v-model="message" />
    <B1 />
  </div>
</template>

<script setup name="B">
import { ref, onActivated, onDeactivated } from 'vue';
import B1 from './B1.vue'
const message = ref('')
onActivated(() => {
  console.log('B onActivated')
})
onDeactivated(() => {
  console.log('B onDeactivated')
})
</script>

<style lang="scss" scoped>
.B{
  border: 1px solid red;
  padding: 10px;
}
input{
  margin-left: 10px;
}
</style>


总结下 onActivated(激.活), onDeactivated(休眠)生命周期钩子的执行顺序:

  1. 由内而外(先执行子组件,再执行父组件的);
  2. 由前到后(先执行上个组件的休眠,再执行下个组件的激活)。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Vue中computed与methods的区别详解

    Vue中computed与methods的区别详解

    这篇文章主要介绍了Vue中computed与methods的区别详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-03-03
  • Vue通过input筛选数据

    Vue通过input筛选数据

    这篇文章主要为大家详细介绍了Vue通过input筛选数据的相关代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-05-05
  • Vue Spa切换页面时更改标题的实例代码

    Vue Spa切换页面时更改标题的实例代码

    本篇文章主要介绍了Vue Spa切换页面时更改标题的实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • Vue 实现可视化拖拽页面编辑器

    Vue 实现可视化拖拽页面编辑器

    这篇文章主要介绍了Vue 实现可视化拖拽页面编辑器的方法,帮助大家更好的理解和使用vue,感兴趣的朋友可以了解下
    2021-02-02
  • vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单

    vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单

    这篇文章主要介绍了vue 右键菜单插件 简单、可扩展、样式自定义的右键菜单,本文给大家分享个例子,给大家及时的非常详细,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2018-11-11
  • vue之数据交互实例代码

    vue之数据交互实例代码

    本篇文章主要介绍了vue之数据交互实例代码,vue中也存在像ajax和jsonp的数据交互,实现向服务器获取数据,有兴趣的可以了解一下
    2017-06-06
  • Vue浅析axios二次封装与节流及防抖的实现

    Vue浅析axios二次封装与节流及防抖的实现

    axios是基于promise的HTTP库,可以使用在浏览器和node.js中,它不是vue的第三方插件,vue-axios是axios集成到Vue.js的小包装器,可以像插件一样安装使用:Vue.use(VueAxios, axios),本文给大家介绍axios的二次封装和节流与防抖
    2022-08-08
  • Vue父子组件之间的通信实例详解

    Vue父子组件之间的通信实例详解

    在vue组件通信中其中最常见通信方式就是父子组件之中的通信,而父子组件的设定方式在不同情况下又各有不同。这篇文章主要介绍了Vue---父子组件之间的通信,需要的朋友可以参考下
    2018-09-09
  • vue实现两个区域滚动条同步滚动

    vue实现两个区域滚动条同步滚动

    这篇文章主要为大家详细介绍了vue实现两个区域滚动条同步滚动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • vue基于Element按钮权限实现方案

    vue基于Element按钮权限实现方案

    这篇文章主要介绍了vue基于Element按钮权限实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04

最新评论