可控制缓存销毁keepAlive组件
我的代码果然有问题 人气:0简介
关于 Vue 的 KeepAlive
<KeepAlive>
是一个内置组件,它的功能是在多个组件间动态切换时 缓存 被移除的组件实例
我们可以利用这一特性来解决当路由切换时页面组件被销毁的问题,常见的业务场景有表单缓存,列表缓存定位,返回时保持状态等,网上有很多教程涉及,但是对如何自主控制缓存的组件销毁这一块大多讲的不是很清晰。
本文会以初学者的角度出发,一步一步带你了解 keepAlive 的特性并实现一个可以自主控制什么时候销毁缓存页面的 keepAlive 组件 —— app-router-view
思路
在编写这一组件时我们的思路是先在路由配置中加入缓存标识,然后在<router-view>
组件里加上<KeepAlive>
标签,然后通过缓存标识判断是否缓存该组件,为了操作缓存的销毁,我们会用到 include 属性,通过操作 include 里的组件名实现自主销毁组件,以下是具体实现步骤。
在 Routes 中添加 keepAlive 缓存标识
const routes = [ { path: '/index', name: 'index', component: () => import('@/views/index.vue'), meta: { title: '首页', keepAlive: false // 缓存标识 } } ]
创建 app-router-view 组件
<template> <router-view v-slot="{ Component, route }"> <keep-alive> <component :is="Component" v-if="route.meta.keepAlive"/> </keep-alive> <component :is="Component" v-if="!route.meta.keepAlive"/> </router-view> </template>
这就是大家平时看教程比较常见的模式了,也能实现一些简单的需求,但还存在问题,就是当我们不需要缓存时候无法手动清除缓存,等会继续完善,这里先给大家简单介绍下<router-view>
的 v-slot 和标签里的 :is 是做什么的,这两个东西工作中并不常用,新同学可能比较陌生,这里也简单科普下。
router-view 中的 v-slot
简单说 v-slot 可以让我们方便的拿到路由标签包裹的组件和路由对象
主要用于方便我们使用 <transition>
和 <keep-alive>
组件来包裹我们自己的组件
标签里的 :is
官网介绍是用于绑定动态组件,简单说就是可以让标签转化为我们指定的 vue 组件
实现手动清除页面缓存
这里简单说下思路,<keep-alive>
标签上有 include 属性,会接收一个数组,数组里的值是我们要缓存页面的组件名,我们可以通过操作 include 的值来手动销毁我们的缓存页面。
这里需要特别注意这个组件名,没有理解好这一块实践中就会出现各种奇奇怪怪的问题!!!
组件名指的是 vue 组件定义时的那个命名,同时我们 routes 里定义的 name 需要与之对应,否则找不到关系,以下图为例,默认情况下,我们 vue 的文件名就是我们最终引入的组件名,即 list-one 与 list-two 就是需要我们维护在 routes 中的名字
了解了这一点后我们来开始代码实现
定义组件名的方法
一般情况下我们可以通过文件名称来做组件名,但是很多时候我们会遇到文件名称一样的问题,这时候就需要我们自定义组件名了,这里推荐两种方法原生模式和插件模式
- 原生模式
<script> export default { name: 'component-name' // 你的组件名 } </script>
- 插件模式
使用 vite-plugin-vue-setup-extend 插件扩展语法糖
// 安装插件 npm i unplugin-vue-components -D // 在页面 script setup 标签中定义 name <script setup name="component-name"> // This starter template is using Vue 3 <script setup> SFCs // ... </script>
配置好路由 name 与组件 name 对应关系
{ path: '/list-one', name: 'list-one', component: () => import('@/views/list-one.vue'), meta: { title: '列表 1', keepAlive: false } }, { path: '/list-two', name: 'list-two', component: () => import('@/views/list-two.vue'), meta: { title: '列表 2', keepAlive: true } }
在 pinia 或者 vuex 中定义好操作缓存列表的方法
我这里以 pinia 为例,创建 useKeepAliverStore 模块,通过 add , 与 remove 操作缓存列表
/** * @description: 缓存控制 */ export const useKeepAliverStore = defineStore('keepAliver', { state: () => ({ caches: [] }), getters: {}, actions: { add(name) { if (!this.caches.includes(name)) { this.caches.push(name) } }, remove(name) { this.caches = this.caches.filter((item) => item !== name) }, clear() { this.caches = [] } } })
添加路由守卫,在页面进入时维护缓存列表
import { useKeepAliverStore } from '@/store/modules/keepAliver' export function setupKeepAliver(router) { router.beforeEach((to, from, next) => { if (to.meta.keepAlive) { console.log('keepAliver') const { add } = useKeepAliverStore() add(to.name) } next() }) }
调整组件,维护好 include
<script setup> // This starter template is using Vue 3 <script setup> SFCs import { useKeepAliverStore } from '@/store/modules/keepAliver' const { caches } = storeToRefs(useKeepAliverStore()) </script> <template> <router-view v-slot="{ Component, route }"> <keep-alive :include="caches"> <component :is="Component" v-if="route.meta.keepAlive" :key="route.name" /> </keep-alive> <component :is="Component" v-if="!route.meta.keepAlive" :key="route.name" /> </router-view> </template>
这样就大功告成啦,当我们想要销毁某个页面,只要调用下 remove 方法移除 caches 里对应的组件名,就可以销毁该页面的缓存了
加载全部内容