关于Vue3项目使用keep-alive缓存组件导致切换账号后列表内容为缓存数据问题

方案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);
    }
  }
);
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • """1.个性化消息: 将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello ...
    她即我命阅读 14,437评论 0赞 6
  • 为了让我有一个更快速、更精彩、更辉煌的成长,我将开始这段刻骨铭心的自我蜕变之旅!从今天开始,我将每天坚持阅...
    李薇帆阅读 5,068评论 1赞 4
  • 似乎最近一直都在路上,每次出来走的时候感受都会很不一样。 1、感恩一直遇到好心人,很幸运。在路上总是...
    时间里的花Lily阅读 4,104评论 1赞 3
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 5,008评论 1赞 2
  • 一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取)矩形、椭圆选框工具 【M】移动工具 【V...
    墨雅丫阅读 5,319评论 0赞 0

友情链接更多精彩内容