Vue内置组件KeepAlive——缓存组件实例

keep-alive 是一个Vue内置组件,它的功能是在多个组件间动态切换时缓存被移除的组件实例,而不是销毁它们。

【注意】这玩意儿可不是Vue3独有的,在Vue2中就已经有了,只不过没有像Vue3那样直接显示在文档首页的侧边栏中。

使用意义

  • 性能优化:避免组件重复渲染带来的性能开销
  • 状态保持:保留组件状态(数据、滚动位置等)
  • 用户体验:实现页面的快速切换,保持用户操作状态

日常场景

  1. 对于列表页面,点击列表项跳转到详情页面;
  2. 再从详情页面返回到列表页面:
    1. 列表页面重新加载?重置了数据?
    2. 列表页面原数据加载?但页面却回滚到顶部?
    3. 列表页面保持跳转前的状态,位置不变(这个才是对用户友好的方案)

页面重新加载源于页面从销毁又到呈现的状态切换;

如果可以留存住页面状态或不让页面销毁那页面便不需要重建------使用keep-alive做页面缓存

使用方法

基本用法

html 复制代码
<!-- 非活跃的组件将会被缓存! -->
<KeepAlive>
  <component :is="activeComponent" />
</KeepAlive>

搭配RouterView当在处理 KeepAlive** **组件时,我们通常想要保持路由组件活跃,而不是 RouterView 本身。为了实现这个目的,我们可以将 KeepAlive 组件放置在插槽内:

html 复制代码
<router-view v-slot="{ Component }">
  <keep-alive>
    <component :is="Component" />
  </keep-alive>
</router-view>

包含和排除

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

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

html 复制代码
<!-- 以英文逗号分隔的字符串 -->
<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>

搭配路由渲染

javascript 复制代码
import { createRouter, createWebHistory } from 'vue-router'
import List from '../components/list.vue'
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      component: () => import('../components/layout.vue'),
      redirect: '/home',
      children: [
        {
          path: '/home',
          component: () => import('../components/home.vue')
        },
        {
          path: '/list',
          // component: List,
          component: () => import('../components/lista.vue'),
          // 配置自定义属性keepAlive,在路由加载页面时做条件渲染
          meta: {
            keepAlive: true
          }
        },
        {
          path: '/myinfo',
          component: () => import('../components/myinfo.vue')
        },
        {
           path: '/iteminfo',
           component: () => import('../components/iteminfo.vue')
        }
      ]
    }
  ]
})
export default router
html 复制代码
<!-- Layout.vue -->
 <router-view v-slot="{ Component }">
      <component :is="Component" :key="route.path" v-if="!route.meta?.keepAlive" />
      <keep-alive>
        <component :is="Component" :key="route.path" v-if="route.meta?.keepAlive" />
      </keep-alive>
</router-view>

缓存数量

可以通过传入**++max++** 来限制可被缓存的最大组件实例数(组件数量)。

如果缓存的实例数量即将超过指定的那个最大数量,则最久没有被访问的缓存实例将被销毁,以便为新的实例腾出空间。

html 复制代码
<KeepAlive :max="10">
  <component :is="activeComponent" />
</KeepAlive>

生命周期

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

javascript 复制代码
<script setup>
import { onActivated, onDeactivated } from 'vue'

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

onDeactivated(() => {
  // 在从 DOM 上移除、进入缓存
  // 以及组件卸载时调用
})
</script>
  • onActivated 在组件挂载时也会调用,并且 onDeactivated 在组件卸载时也会调用。
  • 这两个钩子不仅适用于 <KeepAlive> 缓存的根组件,也适用于缓存树中的后代组件。

其他

举一反三:

当前的iteminfo页面路由处于layout管辖下,如若将iteminfo路由提至layout同级,怎么完成对list的缓存处理?

要先稳住layout,否则layout保不住,更别提保layout的子路由list了。

javascript 复制代码
import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path:'/',
      component:()=>import('../components/Layout.vue'),
      redirect:'/home',
      children:[
        {
          path:'/home',
          component:()=>import('../components/Home.vue')
        },
        {
          path:'/list',
          component:()=>import('../components/List.vue'),
          meta:{
            keepAlive:true
          }
        },
        {
          path:'/myinfo',
          component:()=>import('../components/Myinfo.vue')
        },
        // {
        //   path:'/iteminfo',
        //   component: () => import('../components/ItemInfo.vue')
        // }
      ]
    },
    // 挪到了外层,和layout同级
    {
      path:'/iteminfo',
      component: () => import('../components/ItemInfo.vue')
    }
  ],
})

export default router
html 复制代码
<!-- App.vue -->
<script setup>

</script>

<template>
  <router-view v-slot="{ Component }">
    <!-- 要先稳住layout,否则layout保不住,更别提保layout的子路由list了 -->
    <KeepAlive include="Layout">
      <component :is="Component" />
    </KeepAlive>
  </router-view>
</template>

<style scoped></style>
相关推荐
慧一居士11 小时前
Element Plus 按需引入的配置使用说明和完整示例
前端·vue.js
gis开发之家13 小时前
《Vue3 从入门到大神35篇》Vue3 源码详解(五):effect 依赖收集原理——track 与 trigger 是如何工作的?
javascript·typescript·前端框架·vue3·vue3源码
时空无限14 小时前
vllm 缓存对模型启动时间的影响
缓存·vllm
CoderWeen15 小时前
我写了个能一步步点着看的 Dijkstra 可视化项目(Vue3 + Leaflet + Generator)
前端·javascript·vue.js
无人生还15 小时前
第 1 篇:从 Vue3 到 React 的思维转变
前端·vue.js·react.js
就业发动机15 小时前
我用 Tauri 做了一个约 1.5 MB 的开源屏幕标注工具:MarkerOn
vue.js·rust
爱分享的程序猿-Clark16 小时前
【前端分享】vue开发项目,如何实现 从A页面跳转到B页面,并传值!
前端·javascript·vue.js
徐小夕16 小时前
花了3天,我写了一款开源AI公众号编辑器
前端·vue.js·github
come1123417 小时前
Vue 2 与 Vue 3 语法区别及使用技巧
前端·javascript·vue.js
腻害兔17 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:ERP 企业资源模块,一个轻量级进销存的完整实现?
前端·javascript·vue.js·人工智能·前端框架·产品经理·ai编程