Vue后台管理系统:实现动态组件命名与页面缓存

130 阅读1分钟

背景

领导要求后台管理系统实现tabs标签页功能,每个页面打开后需显示标签并缓存页面。
使用Pinia定义一个tagStore保存路由路径,并结合keepalive实现缓存。
但是遇上了缓存的页面组件需要命名才能生效的问题,但是老系统页面组件太多了
给每个组件都命名是不存在的 🙃。

实现页面缓存示例

vue_sfc
<tabs/> <!-- 标签栏组件 实现省略:就是标签的增删改查和tagStore.tags数组的维护 -->
<router-view v-slot="{ Component, route }">
  <keep-alive :include="keepAliveNames">
    <component :is="Component" :key="route.fullPath"/>
  </keep-alive>
</router-view>

<script setup>
import { computed } from 'vue';
import { useTagStore } from '@/stores/tagStore';

const tagStore = useTagStore();
const keepAliveNames = computed(() => {
  return tagStore.tags.filter((item) => item.keepAlive).map((item) => item.name);
});
</script>

遇到的问题

配置后缓存不生效,原因是页面组件未设置名称,而keep-alive需要组件有名称。

解决方案

后台有好几百个页面,不可能手动设置每个页面的名称。系统的菜单是动态配置的,接口返回菜单名称和组件地址。在配置菜单时添加name字段,并确保后端接口校验其唯一性。

const modules = import.meta.glob(['../pages/**/*.vue']);

// 遍历后端返回的菜单并且动态添加路由(省略..)
// 在添加路由时,给每个路由配置component
// route 就是根据后端接口返回的菜单组装的数据。后面需要被添加到路由:router.push(route)
route.component = () => {
// modules[`../pages/${route.routeName}/index.vue`] 形如: ()=>import('xxx.vue') 
  return modules[`../pages/${routeName}/index.vue`]().then((m) => {
    if (route.name && m && m.default) {
      m.default.name = route.name;
    }
    return m;
  });
};

总结

利用Vue Router的路由接收Promise的特性,按需加载页面路由组件,并在加载后为组件命名,配合keepalive实现页面缓存。