问题
连续两天遇到keepalive问题,第一个问题是三级路由嵌套router-view没法缓存问题,第二个问题是使用keepalive导致组件渲染两次问题,深坑。。。
解决思路
引入routerHelper,createRouter时三级路由提升为两层
import { deepClone } from '@/utils'; import { createRouter, createWebHashHistory } from 'vue-router'; /** * 将多级路由转换为 2 级路由 */ export function flatMultiLevelRoutes(routeModules) { const modules = deepClone(routeModules); for (let index = 0; index < modules.length; index++) { const routeModule = modules[index]; // 判断级别是否 多级 路由 if (!isMultipleRoute(routeModule)) { // 声明终止当前循环, 即跳过此次循环,进行下一轮 continue; } // 路由等级提升 promoteRouteLevel(routeModule); } return modules; } // 路由等级提升 function promoteRouteLevel(routeModule) { // Use vue-router to splice menus // 使用vue-router拼接菜单 // createRouter 创建一个可以被 Vue 应用程序使用的路由实例 let router = createRouter({ routes: [routeModule], history: createWebHashHistory(), }); // getRoutes: 获取所有 路由记录的完整列表。 const routes = router.getRoutes(); // 将所有子路由添加到二级路由 addToChildren(routes, routeModule.children || [], routeModule); router = null; // 对传入的item对象的children进行删除 routeModule.children = routeModule.children?.map((item) => { item.children = undefined; return item; }); } // 将所有子路由添加到二级路由 function addToChildren(routes, children, routeModule) { for (let index = 0; index < children.length; index++) { const child = children[index]; const route = routes.find((item) => item.name === child.name); if (!route) { continue; } routeModule.children = routeModule.children || []; if (!routeModule.children.find((item) => item.name === route.name)) { routeModule.children?.push(route); } if (child.children?.length) { addToChildren(routes, child.children, routeModule); } } } // 判断级别是否超过2级 function isMultipleRoute(routeModule) { // Reflect.has 与 in 操作符 相同, 用于检查一个对象(包括它原型链上)是否拥有某个属性 if ( !routeModule || !Reflect.has(routeModule, 'children') || !routeModule.children?.length ) { return false; } const children = routeModule.children; let flag = false; for (let index = 0; index < children.length; index++) { const child = children[index]; if (child.children?.length) { flag = true; break; } } return flag; }
// 使用
const router = createRouter({
history: createWebHashHistory(),
routes: [...flatMultiLevelRoutes(constantRoutes)], // 菜单用constantRoutes来循环生成,而createRouter用调整过的路由
});