头图

说明

keep-alive标签可以让组件持续存活,避免路由刷新造成的页面数据丢失。
加入你在A组件填写表单,切换到B组件,此时再返回A组件,正常情况下,组件会刷新,数据会丢失。
如果该页面被keep-alive缓存,那么路由跳转切换后,数据还在。
我们来看官方示例:
keep-alive
KeepAlive

<template>
    <!-- 将(只)缓存组件name为a或者b的组件, 结合动态组件使用 -->
    <keep-alive include="a,b">
          <component :is="view"></component>
    </keep-alive>

    <!-- 组件name为c的组件不缓存(可以保留它的状态或避免重新渲染) -->
    <keep-alive exclude="c"> 
          <component :is="view"></component>
    </keep-alive>
    
    <!-- 使用正则表达式,需使用v-bind -->
    <keep-alive :include="/a|b/">
          <component :is="view"></component>
    </keep-alive>

    <!-- 动态判断 -->
    <keep-alive :include="includedComponents">
        <router-view></router-view>
    </keep-alive>
    
    <!-- 如果同时使用include,exclude,那么exclude优先于include, 下面的例子只缓存a组件 -->
    <keep-alive include="a,b" exclude="b"> 
          <component :is="view"></component>
    </keep-alive>

    <!-- 如果缓存的组件超过了max设定的值5,那么将删除第一个被缓存的组件 -->
    <keep-alive exclude="c" max="5"> 
      <component></component>
    </keep-alive>
</template>

在上面的示例中,我们通过keep-alive缓存组件,如果组件name符合keep-alive缓存规则,该组件即可被被缓存。
使用keep-alive缓存组件会触发以下生命周期钩子函数

  1. onActivated - 在组件被激活时触发。
  2. onDeactivated - 在组件被停用时触发。

而以下生命周期钩子函数不会被触发

  1. setup 开始创建组件,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
  2. onBeforeMount 组件挂载到节点上之前执行的函数;
  3. onMounted 组件挂载完成后执行的函数;
  4. onBeforeUpdate 组件更新之前执行的函数;
  5. onUpdated 组件更新完成之后执行的函数;
  6. onBeforeUnmount 组件卸载之前执行的函数;
  7. onUnmounted 组件卸载完成后执行的函数;

这些生命周期钩子函数不会被触发是因为被keep-alive缓存的组件实例在被激活和离开缓存时,并不会重新创建或销毁,而是被缓存起来直接展示或隐藏,初次加载组件会照常触发7个生命周期,而离开后返回时则仅仅触发组件的2个生命周期函数

组件name

我们在vue3中给组件添加name有两种方式,组件的name可以用于keep-aliveinclude缓存
方式一
新增一个script,通过export default将组件name暴露出去。

<script lang="ts">
export default {
    name: "myName",    
}
</script>
  
<script setup lang="ts">
import { ref, reactive } from "vue"
import { Plus, CircleClose } from "@element-plus/icons-vue"
import type { FormInstance } from "element-plus"
// 正常js逻辑......
</script>

方式二
通过插件实现

npm install vite-plugin-vue-setup-extend -D

vite.config.ts文件中配置

import vuesetupExtend from 'vite-plugin-vue-setup-extend'

export default defineConfig({
  plugins: [vue(),vuesetupExtend()], // 在这里引入
  // resolve:{}
})

引入完成后,在页面中的script上可以直接定义name

<script setup lang="ts" name="myName>
import { ref, reactive } from "vue"
import { Plus, CircleClose } from "@element-plus/icons-vue"
import type { FormInstance } from "element-plus"
// 正常js逻辑......
</script>

路由缓存

我们先来看一组代码

<router-view v-slot="{ Component }">
  <keep-alive :include="cachedViews">
  <component :is="Component"/>
  </keep-alive>
</router-view>

上面的写法实质上跟直接使用router-view的效果是一致的,如下:

<router-view></router-view>

我们通过router-view设置路由出口来渲染页面,另外它可以通过插槽的形式动态渲染组件,通过插槽组件的形式渲染的目的是为了配合keep-alive设置页面缓存。

在这里cachedViews的数据应该是一个数组,来源于router的可缓存选项,我们在keep-alive中利用include来动态判断该组件是否缓存,如果组件name在缓存数组cachedViews中,该组件即可缓存。
image.png
我们在动态添加路由的时候会根据路由是否可缓存选项来设置缓存name,例如:

{
    path: "/module-view/Amap",
        name: "Amap",  // 取该路由的name
        component: () =>
        import("@/views/module-view/Amap/index.vue"),
        meta: {
        title: "Amap",
            isLink: "",
            isHide: false,
            isKeepAlive: true,  // 路由是否缓存
            isAffix: false,
            isIframe: false,
            roles: ["admin"],
            icon: "Menu"
    }
},

我们在遍历生成路由时根据isKeepAlive来生成数据,我们可以将该数据存入全局store中,为读取缓存提供支持。


兔子先森
420 声望18 粉丝

致力于新技术的推广与优秀技术的普及。