方案1.使用清理工具
/**
* 登出时缓存清理工具
* 在用户登出时直接清除除了 /home 页面外的所有 keep-alive 缓存
*/
import { watch } from "vue";
import { useGlobalStore } from "@/stores/global";
import { keepAliveNames } from "@/utils/RouteCache";
// 需要保留的页面缓存(登出后仍然保持缓存)
const KEEP_CACHE_PAGES = ["Home"];
// 全局 keep-alive 缓存引用
let globalKeepAliveCache: Map<any, any> | null = null;
/**
* 注册 keep-alive 缓存引用
* 在 App.vue 中调用,保存 keep-alive 实例的缓存引用
*/
export function registerKeepAliveCache(cache: Map<any, any>) {
globalKeepAliveCache = cache;
console.log("📦 keep-alive 缓存引用已注册");
}
/**
* 清理指定的 keep-alive 缓存
* @param cacheNames 要清理的缓存名称数组
*/
function clearKeepAliveCache(cacheNames: string[]) {
if (!globalKeepAliveCache) {
console.warn("⚠️ keep-alive 缓存引用未注册");
return;
}
let clearedCount = 0;
// 遍历缓存,找到匹配的组件并删除
for (const [key, cachedVNode] of globalKeepAliveCache) {
const componentName = cachedVNode?.type?.name || cachedVNode?.type?.__name;
if (componentName && cacheNames.includes(componentName)) {
globalKeepAliveCache.delete(key);
clearedCount++;
console.log(`🧹 清理 keep-alive 缓存: ${componentName}`);
}
}
console.log(`✅ 登出缓存清理完成,共清理 ${clearedCount} 个页面缓存`);
}
/**
* 设置登出时的缓存清理
*/
export function setupLogoutCacheClear() {
const globalStore = useGlobalStore();
// 监听 token 变化,检测登出
watch(
() => globalStore.token,
(newToken, oldToken) => {
// 如果从有 token 变为无 token(登出)
if (oldToken && !newToken) {
console.log("🔄 检测到用户登出,开始清理缓存");
计算需要清理的页面缓存
const cachesToClear = keepAliveNames.filter((name) => !KEEP_CACHE_PAGES.includes(name));
console.log("📋 需要清理的缓存页面:", cachesToClear);
console.log("🏠 保留的缓存页面:", KEEP_CACHE_PAGES);
// 3. 清理组件缓存
if (cachesToClear.length > 0) {
// 延迟执行,确保登出流程完成
setTimeout(() => {
clearKeepAliveCache(cachesToClear);
}, 100);
}
}
}
);
console.log("✅ 登出缓存清理监听器已设置");
}
/**
* 手动清理所有缓存(除了保留页面)
*/
export function manualClearCache() {
const cachesToClear = keepAliveNames.filter((name) => !KEEP_CACHE_PAGES.includes(name));
clearKeepAliveCache(cachesToClear);
}
/**
* 添加需要保留的页面
*/
export function addKeepCachePage(pageName: string) {
if (!KEEP_CACHE_PAGES.includes(pageName)) {
KEEP_CACHE_PAGES.push(pageName);
console.log(`📌 添加保留缓存页面: ${pageName}`);
}
}
/**
* 移除保留的页面
*/
export function removeKeepCachePage(pageName: string) {
const index = KEEP_CACHE_PAGES.indexOf(pageName);
if (index > -1) {
KEEP_CACHE_PAGES.splice(index, 1);
console.log(`🗑️ 移除保留缓存页面: ${pageName}`);
}
}
组件:
//src/components/CustomKeepAlive.vue
<template>
<keep-alive :include="include" ref="keepAliveRef">
<slot />
</keep-alive>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { registerKeepAliveCache } from '@/utils/LogoutCacheClear';
// Props
interface Props {
include?: string | string[] | RegExp;
}
defineProps<Props>();
// 模板引用
const keepAliveRef = ref();
// 组件挂载后注册缓存引用
onMounted(() => {
if (keepAliveRef.value) {
// 获取 keep-alive 实例的缓存
const cache = keepAliveRef.value.$.ctx.cache;
if (cache) {
registerKeepAliveCache(cache);
}
}
});
</script>
应用:
<CustomKeepAlive :include="keepAliveName">
<component :is="Component" :key="getKey()" />
</CustomKeepAlive>
方案2.keepAliveName动态调整
单独声明需要清理缓存数据的组件,根据登录切换账号来调整includes的组件内容
// 监听用户信息变化,更新 keep-alive 缓存
const cachePages=['PageA'];
const keepAliveNames = ['PageA','Home'];
watch(
() => globalStore.token,
(newVal) => {
if (!newVal) {
// 获取 keep-alive 实例的缓存
keepAliveName.value = keepAliveNames;
} else {
keepAliveName.value = keepAliveNames.concat(cachePages);
}
}
);