fix: 🐛 (keep-alive)重构缓存机制

- 移除 KeepCache 组件,直接在 AppMain 中实现缓存逻辑

- 将 fullPath 做为组件缓存的 name
This commit is contained in:
zimo493
2025-09-01 11:11:45 +08:00
parent e37a6c5aa4
commit cc3750c128
9 changed files with 128 additions and 142 deletions

View File

@@ -15,21 +15,20 @@ export const usePermissionStore = defineStore("permission", () => {
// 动态路由是否已生成
const isDynamicRoutesGenerated = ref(false);
const allCacheRoutes = ref<string[][]>([]);
/**
* 生成动态路由
*/
async function generateRoutes(): Promise<RouteRecordRaw[]> {
try {
const data = await MenuAPI.getRoutes(); // 获取当前登录人拥有的菜单路由
const dynamicRoutes = parseDynamicRoutes(data);
const dynamicRoutes = parseDynamicRoutes(processRoutes(data));
routes.value = [...constantRoutes, ...dynamicRoutes];
setAllCacheRoutes(routes.value);
isDynamicRoutesGenerated.value = true;
console.log("dynamicRoutes", dynamicRoutes);
return dynamicRoutes;
} catch (error) {
console.error("❌ Failed to generate routes:", error);
@@ -64,33 +63,10 @@ export const usePermissionStore = defineStore("permission", () => {
isDynamicRoutesGenerated.value = false;
};
/**
* 获取所有的缓存路由
* @param userRoutes 用户路由配置
*/
const setAllCacheRoutes = (userRoutes: RouteRecordRaw[]) => {
if (!userRoutes?.length) {
allCacheRoutes.value = [];
return;
}
const result: string[][] = [];
userRoutes.forEach((route) => {
if (route.children?.length) {
traverseRoutes(route.children, [], result);
}
});
allCacheRoutes.value = result;
};
return {
routes,
mixLayoutSideMenus,
isDynamicRoutesGenerated,
allCacheRoutes,
generateRoutes,
setMixLayoutSideMenus,
resetRouter,
@@ -109,12 +85,13 @@ const parseDynamicRoutes = (rawRoutes: RouteVO[]): RouteRecordRaw[] => {
rawRoutes.forEach((route) => {
const normalizedRoute = { ...route } as RouteRecordRaw;
// console.log();
// 处理组件路径
normalizedRoute.component =
normalizedRoute.component?.toString() === "Layout"
? Layout
: modules[`../../views/${normalizedRoute.component}.vue`] ||
modules["../../views/error-page/404.vue"];
: modules[`../../views/${normalizedRoute.component}.vue`];
// 递归解析子路由
if (normalizedRoute.children) {
@@ -128,24 +105,31 @@ const parseDynamicRoutes = (rawRoutes: RouteVO[]): RouteRecordRaw[] => {
};
/**
* 遍历路由树收集缓存路由
* @param nodes 路由节点
* @param path 当前路径
* @param result 结果数组
* 去除中间层的路由 `component` 属性
* @param routes 路由数组
* @param isTopLevel 是否是顶层路由
*/
const traverseRoutes = (nodes: RouteRecordRaw[], path: string[], result: string[][]) => {
nodes.forEach((node) => {
const newPath: string[] = node.name ? [...path, String(node.name)] : [...path];
const processRoutes = (routes: RouteVO[], isTopLevel: boolean = true): RouteVO[] => {
return routes.map((route) => {
// 创建新对象
const newRoute: RouteVO = {
path: route.path,
name: route.name,
children: route.children,
meta: { ...route.meta },
};
// 叶子节点且需要缓存
if (!node.children?.length && node.meta?.keepAlive) {
result.push(newPath);
// 如果是顶层或者component不是"Layout"保留component属性
if (isTopLevel || route.component !== "Layout") {
newRoute.component = route.component;
}
// 递归处理子节点
if (node.children?.length) {
traverseRoutes(node.children, newPath, result);
// 递归处理children标记为非顶层
if (route.children && route.children.length > 0) {
newRoute.children = processRoutes(route.children, false);
}
return newRoute;
});
};

View File

@@ -27,16 +27,15 @@ export const useTagsViewStore = defineStore("tagsView", () => {
/**
* 添加缓存视图到缓存视图列表中
*/
function addCachedView(view: TagView) {
const viewName = view.name;
function addCachedView({ fullPath, keepAlive }: TagView) {
// 如果缓存视图名称已经存在于缓存视图列表中,则不再添加
if (cachedViews.value.includes(viewName)) {
if (cachedViews.value.includes(fullPath)) {
return;
}
// 如果视图需要缓存keepAlive则将其路由名称添加到缓存视图列表中
if (view.keepAlive) {
cachedViews.value.push(viewName);
if (keepAlive) {
cachedViews.value.push(fullPath);
}
}
@@ -57,9 +56,9 @@ export const useTagsViewStore = defineStore("tagsView", () => {
}
function delCachedView(view: TagView) {
const viewName = view.name;
const { fullPath } = view;
return new Promise((resolve) => {
const index = cachedViews.value.indexOf(viewName);
const index = cachedViews.value.indexOf(fullPath);
if (index > -1) {
cachedViews.value.splice(index, 1);
}
@@ -76,9 +75,9 @@ export const useTagsViewStore = defineStore("tagsView", () => {
}
function delOtherCachedViews(view: TagView) {
const viewName = view.name as string;
const { fullPath } = view;
return new Promise((resolve) => {
const index = cachedViews.value.indexOf(viewName);
const index = cachedViews.value.indexOf(fullPath);
if (index > -1) {
cachedViews.value = cachedViews.value.slice(index, index + 1);
} else {
@@ -136,7 +135,7 @@ export const useTagsViewStore = defineStore("tagsView", () => {
return true;
}
const cacheIndex = cachedViews.value.indexOf(item.name);
const cacheIndex = cachedViews.value.indexOf(item.fullPath);
if (cacheIndex > -1) {
cachedViews.value.splice(cacheIndex, 1);
}
@@ -158,6 +157,11 @@ export const useTagsViewStore = defineStore("tagsView", () => {
if (index <= currIndex || item?.affix) {
return true;
}
const cacheIndex = cachedViews.value.indexOf(item.fullPath);
if (cacheIndex > -1) {
cachedViews.value.splice(cacheIndex, 1);
}
return false;
});
resolve({
visitedViews: [...visitedViews.value],
@@ -232,37 +236,6 @@ export const useTagsViewStore = defineStore("tagsView", () => {
}
}
const setCacheRoutes = (names: string[], allCacheRoutes: string[][]) => {
if (!names?.length) {
cachedViews.value = [];
return;
}
cachedViews.value = findAndMergeRouteArrays(allCacheRoutes, names);
};
/**
* 查找并合并路由数组
* @param data 所有缓存路由数据
* @param elements 目标元素
* @returns 合并后的路由数组
*/
const findAndMergeRouteArrays = (data: string[][], elements: string[]): string[] => {
const foundArrays = elements
.map((element) => data.find((arr) => arr.includes(element)))
.filter(Boolean) as string[][];
// 使用Set去重并合并
const mergedSet = new Set<string>();
foundArrays.forEach((arr) => {
arr.forEach((item) => mergedSet.add(item));
});
return Array.from(mergedSet);
};
return {
visitedViews,
cachedViews,
@@ -284,6 +257,5 @@ export const useTagsViewStore = defineStore("tagsView", () => {
closeCurrentView,
isActive,
toLastView,
setCacheRoutes,
};
});