【前端】VUE 缓存动态页面 JeecgBoot切换tab缓存标签页

【前端】VUE 缓存动态页面 JeecgBoot切换tab缓存全部标签页 

src/layouts/page/index.vue

<template>
  <!-- 模板保持不变 -->
  <RouterView>
    <template #default="{ Component, route }">
      <keep-alive v-if="openCache" :include="cachedNames">
        <component :is="Component" :key="routeKey(route, Component)" />
      </keep-alive>
      <component v-else :is="Component" :key="routeKey(route, Component)" />
    </template>
  </RouterView>
  <FrameLayout v-if="getCanEmbedIFramePage" />
</template>

<script lang="ts">
  import { computed, defineComponent, ref, watch } from 'vue';
  import FrameLayout from '/@/layouts/iframe/index.vue';
  import { useRootSetting } from '/@/hooks/setting/useRootSetting';
  import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
  import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
  import { useMultipleTabStore } from '/@/store/modules/multipleTab';
  import { useRoute, RouteLocationNormalized } from 'vue-router';

  export default defineComponent({
    name: 'PageLayout',
    components: { FrameLayout },
    setup() {
      const { getShowMultipleTab } = useMultipleTabSetting();
      const tabStore = useMultipleTabStore();
      const { getOpenKeepAlive, getCanEmbedIFramePage } = useRootSetting();
      const { getBasicTransition, getEnableTransition } = useTransitionSetting();
      const openCache = computed(() => getOpenKeepAlive.value && getShowMultipleTab.value);

      const cachedNames = ref<string[]>([]);
      const route = useRoute();

      // 存储路由路径与组件名称的映射
      const routeComponentMap = new Map<string, string>();

      // 存储当前标签页数量
      const lastTabCount = ref(0);

      /**
       * 自动收集所有访问过的组件名称
       */
      watch(
        () => route.fullPath,
        () => {
          const comp = route.matched?.slice(-1)[0]?.components?.default;
          if (!comp) return;

          // 取组件的 name
          let compName = comp.name;

          // 如果组件没有 name,就动态生成一个唯一的
          if (!compName) {
            compName = `Route_${route.name || route.path.replace(/\//g, '_')}`;
            comp.name = compName; // 挂到组件实例上
          }

          // 存储路由与组件名称的映射
          routeComponentMap.set(route.fullPath, compName);

          // 加入缓存列表
          if (!cachedNames.value.includes(compName)) {
            cachedNames.value.push(compName);
          }

          // 更新标签页数量
          lastTabCount.value = tabStore.getTabList.length;
        },
        { immediate: true }
      );

      // 监听标签页数量变化
      watch(
        () => tabStore.getTabList.length,
        (newCount) => {
          // 如果标签页数量减少,说明有标签页被关闭
          if (newCount < lastTabCount.value) {
            // 获取当前所有标签页的路径
            const currentTabPaths = new Set(tabStore.getTabList.map(tab => tab.fullPath));

            // 检查所有已缓存的路径,删除不在当前标签页中的缓存
            routeComponentMap.forEach((compName, path) => {
              if (!currentTabPaths.has(path)) {
                const index = cachedNames.value.indexOf(compName);
                if (index !== -1) {
                  cachedNames.value.splice(index, 1);
                }
                routeComponentMap.delete(path);
              }
            });
          }

          // 更新标签页数量
          lastTabCount.value = newCount;
        }
      );

      // 保证同一组件不同参数也能缓存
      const routeKey = (route: RouteLocationNormalized, Component: any) => {
        return `${Component?.name || route.name || route.fullPath}_${route.fullPath}`;
      };

      return {
        getBasicTransition,
        getEnableTransition,
        openCache,
        cachedNames,
        getCanEmbedIFramePage,
        routeKey,
      };
    },
  });
</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是Superman丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值