在 Angular 中,{ provide: RouteReuseStrategy, useClass: SimpleReuseStrategy } 是用于 自定义路由复用策略 的配置。它的核心作用是 控制路由切换时是否复用组件实例,从而优化性能和用户体验。以下是详细说明:
1. 默认行为 vs 自定义复用策略
| 场景 | 默认行为 (DefaultRouteReuseStrategy) | 自定义复用 (SimpleReuseStrategy) |
|---|---|---|
| 路由跳转时 | 总是销毁旧组件,创建新组件实例 | 根据规则复用已有组件实例 |
| 组件生命周期 | 每次跳转触发 ngOnDestroy 和 ngOnInit | 复用时不触发销毁和初始化 |
| 内存占用 | 较低(无缓存) | 较高(缓存组件实例) |
| 适用场景 | 简单页面 | 需要保持组件状态的复杂页面(如表格、编辑器) |
2. 核心方法解释
自定义 SimpleReuseStrategy 需实现以下方法:
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';
export class SimpleReuseStrategy implements RouteReuseStrategy {
// 是否允许复用路由
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig; // 默认逻辑
}
// 是否允许缓存路由
shouldDetach(route: ActivatedRouteSnapshot): boolean {
return true; // 所有路由都缓存(按需修改)
}
// 存储路由实例
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle | null): void {
// 缓存逻辑(如存入 Map)
}
// 是否允许恢复路由
shouldAttach(route: ActivatedRouteSnapshot): boolean {
return true; // 总是尝试恢复(按需修改)
}
// 获取缓存的路由实例
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
// 从缓存中获取
}
}
3. 典型应用场景
场景 1:标签页切换保留状态
// 路由配置
{ path: 'user/:id', component: UserDetailComponent }
// 当用户从 /user/1 切换到 /user/2 时:
// - 默认行为:重新创建 UserDetailComponent,丢失之前的滚动位置、表单输入等
// - 使用复用策略:复用组件实例,仅更新数据
场景 2:复杂表格保留过滤条件
// 路由配置
{ path: 'report', component: ReportTableComponent }
// 用户从 /report 跳转到其他页面后返回:
// - 默认行为:重新加载表格,过滤条件重置
// - 使用复用策略:保持表格的过滤、分页状态
4. 完整配置步骤
步骤 1:创建自定义策略类
// simple-reuse-strategy.ts
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router';
export class SimpleReuseStrategy implements RouteReuseStrategy {
private cacheRoutes = new Map<string, DetachedRouteHandle>();
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
return future.routeConfig === curr.routeConfig;
}
shouldDetach(route: ActivatedRouteSnapshot): boolean {
// 只缓存带有 cache=true 的路由
return route.data['cache'] === true;
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
const path = this.getRoutePath(route);
this.cacheRoutes.set(path, handle);
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
const path = this.getRoutePath(route);
return this.cacheRoutes.has(path);
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
const path = this.getRoutePath(route);
return this.cacheRoutes.get(path) || null;
}
private getRoutePath(route: ActivatedRouteSnapshot): string {
return route.pathFromRoot.map(v => v.url.map(segment => segment.toString()).join('/')).join('/');
}
}
步骤 2:注册到应用配置
// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app/routes';
import { SimpleReuseStrategy } from './simple-reuse-strategy';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
{
provide: RouteReuseStrategy,
useClass: SimpleReuseStrategy // 替换默认策略
}
]
};
步骤 3:在路由中标记需要缓存的页面
// routes.ts
const routes: Routes = [
{
path: 'dashboard',
component: DashboardComponent,
data: { cache: true } // ⭐ 标记此路由需要缓存
}
];
5. 注意事项
| 问题 | 解决方案 |
|---|---|
| 内存泄漏 | 限制缓存数量,或提供手动清除缓存的方法 |
| 数据更新问题 | 在复用组件中监听路由参数变化(如使用 ngOnInit 或 ActivatedRoute 参数订阅) |
| 浏览器后退行为不一致 | 在 shouldReuseRoute 中精细控制复用逻辑 |
| 动态路由缓存失效 | 确保路由路径生成逻辑 (getRoutePath) 能唯一标识路由 |
6. 强制刷新缓存组件
当需要手动更新缓存时,可调用以下方法:
export class SimpleReuseStrategy {
// 添加清除缓存方法
clearCache(path: string): void {
if (this.cacheRoutes.has(path)) {
const handle = this.cacheRoutes.get(path)!;
(handle as any).componentRef.destroy(); // 销毁组件
this.cacheRoutes.delete(path);
}
}
}
// 在组件中调用
constructor(private reuseStrategy: SimpleReuseStrategy) {}
refresh(): void {
this.reuseStrategy.clearCache('/dashboard');
this.router.navigate(['/dashboard']);
}