Angular自定义RouteReuseStrategy:父路由导航至子路由时缓存父路由的实现咨询
Angular自定义RouteReuseStrategy:父路由导航至子路由时缓存父路由的实现咨询
嘿,我完全get到你的需求啦——当从父路由导航到子路由时,把父路由的状态缓存下来,这样返回父路由时不用重新初始化组件、丢失之前的状态对吧?结合你给出的路由结构,我来一步步帮你实现这个自定义的RouteReuseStrategy。
核心思路
Angular的RouteReuseStrategy是控制路由复用的核心接口,我们需要实现它的5个关键方法来定制缓存逻辑:
shouldReuseRoute:判断当前路由是否复用默认逻辑shouldDetach:判断是否需要缓存当前路由(离开路由时触发)store:存储缓存的路由快照和组件句柄shouldAttach:判断是否应该恢复之前缓存的路由(进入路由时触发)retrieve:获取缓存的路由句柄
针对你的需求,我们要做到两点:
- 当从父路由(比如你的
DashboardComponent)导航到它的子路由时,缓存父路由 - 当从子路由返回父路由时,复用之前缓存的父路由状态
具体实现步骤
1. 创建自定义RouteReuseStrategy类
新建custom-route-reuse-strategy.ts文件,实现如下逻辑:
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; export class CustomRouteReuseStrategy implements RouteReuseStrategy { // 用Map存储缓存的路由句柄,key为路由唯一标识 private cachedRoutes = new Map<string, DetachedRouteHandle>(); // 判断当前路由是否复用默认逻辑 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { const shouldReuse = future.routeConfig === curr.routeConfig; // 可选:如果跳转到非当前父路由的其他路由,清除父路由缓存(避免内存占用) if (!shouldReuse && curr.data?.shouldReuse === true) { const key = this.generateRouteKey(curr); this.cachedRoutes.delete(key); } return shouldReuse; } // 判断是否需要缓存当前路由:标记了shouldReuse的父路由,且即将跳转到子路由时缓存 shouldDetach(route: ActivatedRouteSnapshot): boolean { return route.data?.shouldReuse === true && route.firstChild !== null; } // 存储路由快照和组件句柄 store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { const key = this.generateRouteKey(route); this.cachedRoutes.set(key, handle); } // 判断是否应该恢复缓存:进入标记了shouldReuse的父路由,且没有子路由激活时恢复 shouldAttach(route: ActivatedRouteSnapshot): boolean { const key = this.generateRouteKey(route); return this.cachedRoutes.has(key) && route.firstChild === null; } // 获取缓存的路由句柄 retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { const key = this.generateRouteKey(route); return this.cachedRoutes.get(key) ?? null; } // 生成路由的唯一标识(用完整路由路径) private generateRouteKey(route: ActivatedRouteSnapshot): string { let fullPath = ''; let currentRoute = route; while (currentRoute) { if (currentRoute.routeConfig?.path) { fullPath = `${currentRoute.routeConfig.path}/${fullPath}`; } currentRoute = currentRoute.parent!; } return fullPath.replace(/\/$/, ''); // 移除末尾斜杠,保证key唯一 } }
2. 在路由配置中标记需要缓存的父路由
修改你的路由配置,给需要缓存的父路由(DashboardComponent)添加data.shouldReuse: true标记,这样逻辑更灵活:
export const routes: Routes = [ { path: "", component: DashboardComponent, canActivate: [ dashboardAuthGuard ], data: { shouldReuse: true }, // 标记该父路由需要缓存 children: [ { path: "app", providers: [ ModalService ], children: [ { path: "sale", loadChildren: () => import("./dashboard/suffapps/sale/sale.module").then(module => module.SaleModule) }, { path: "reports", loadChildren: () => import("./dashboard/suffapps/reports/reports.module").then(module => module.ReportsModule) } ] } ] }, // ...其他路由 ];
3. 在AppModule中提供自定义策略
最后,在根模块中替换默认的RouteReuseStrategy为我们自定义的:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { CustomRouteReuseStrategy } from './custom-route-reuse-strategy'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [AppComponent], imports: [BrowserModule, AppRoutingModule], providers: [ { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } ], bootstrap: [AppComponent] }) export class AppModule { }
额外说明
- 如果你不想用
data.shouldReuse标记,也可以直接在shouldDetach方法里针对特定路由路径判断(比如return route.routeConfig?.path === '' && route.firstChild !== null;),但用data标记的方式更通用,适合后续扩展其他需要缓存的父路由。 - 缓存的路由会占用内存,如果你的应用有很多需要缓存的路由,可以考虑添加缓存清理逻辑(比如在用户退出时清除所有缓存)。
备注:内容来源于stack exchange,提问作者Ersin
相关产品推荐
相关产品推荐

