解决vue-router在3级路由keep-alive后组件加载多次方法
问题
连续两天遇到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: [
], // 菜单用constantRoutes来循环生成,而createRouter用调整过的路由
...flatMultiLevelRoutes(constantRoutes).map((item) => {
item.component = Layout; // 修复组件深拷贝后layout重新渲染
return item;
})
});

浙公网安备 33010602011771号