RouteReuseStrategy 是 Angular 提供的一个服务类,用于自定义路由复用策略。通过它,你可以控制路由组件的缓存、销毁以及重新加载行为。默认情况下,Angular 会在路由切换时销毁当前组件并创建新组件。而通过 RouteReuseStrategy,你可以改变这种行为,比如缓存某些路由的组件实例,以优化性能或提升用户体验。
RouteReuseStrategy 的核心方法
RouteReuseStrategy 是一个抽象类,需要实现以下方法:
shouldDetach(route: ActivatedRouteSnapshot): boolean
-
是否将当前路由的组件缓存下来。
-
返回值:true 表示需要缓存,false 表示不缓存。
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void
-
缓存组件实例。
-
参数:
-
route:当前路由的快照。
-
handle:组件实例的引用。
-
shouldAttach(route: ActivatedRouteSnapshot): boolean
-
是否需要从缓存中加载组件实例。
-
返回值:true 表示从缓存中加载,false 表示重新创建。
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null
-
获取缓存中的组件实例。
-
返回值:缓存的组件实例引用,或者 null(如果没有缓存)。
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean
-
是否复用当前路由。
-
参数:
-
future:将要导航到的路由快照。
-
curr:当前路由快照。
-
-
返回值:true 表示复用,false 表示重新加载。
简单示例
实现一个基础的路由复用策略
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router';
export class CustomRouteReuseStrategy implements RouteReuseStrategy {
private storedRoutes: { [key: string]: DetachedRouteHandle } = {};
shouldDetach(route: ActivatedRouteSnapshot): boolean {
// 控制需要缓存的路由,假设只有路径 'dashboard' 需要缓存
return route.routeConfig?.path === 'dashboard';
}
store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void {
// 将路由组件缓存起来
this.storedRoutes[route.routeConfig?.path || ''] = handle;
}
shouldAttach(route: ActivatedRouteSnapshot): boolean {
// 如果缓存中有对应的路由组件实例,就复用
return !!this.storedRoutes[route.routeConfig?.path || ''];
}
retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null {
// 返回缓存的路由组件实例
return this.storedRoutes[route.routeConfig?.path || ''] || null;
}
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
// 当路由路径相同时复用路由
return future.routeConfig === curr.routeConfig;
}
}
在模块中启用自定义策略
将自定义的 RouteReuseStrategy 添加到 providers 中:
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { CustomRouteReuseStrategy } from './custom-route-reuse-strategy';
@NgModule({
imports: [RouterModule.forRoot(routes)],
providers: [
{ provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy }
],
exports: [RouterModule]
})
export class AppRoutingModule {}
方法之间的关系
RouteReuseStrategy 的核心方法之间有明确的联系,它们共同决定了路由组件是否被缓存、是否从缓存中加载、何时复用等。可以把它们看作一个生命周期流转的过程,每个方法在不同的阶段起到不同的作用。
方法之间的关系和调用顺序
当导航到一个新的路由时,RouteReuseStrategy 的方法会按照以下流程被调用:
1. shouldReuseRoute
-
触发时机:Angular 判断当前路由和目标路由是否相同时,会调用此方法。
-
作用:决定是否复用当前路由。
-
如果返回 true,则当前组件不会被销毁,路由直接复用,不会触发其他方法。
-
如果返回 false,则进入路由切换流程,触发其他方法。
联系:它是整个复用策略的第一步。如果返回 false,Angular 会检查是否需要缓存当前路由组件(进入下一步的 shouldDetach)。
2. shouldDetach
-
触发时机:在路由切换之前,判断是否需要将当前路由组件缓存。
-
作用:返回 true 时,Angular 会缓存当前路由组件实例,并调用 store 方法。
联系:如果 shouldDetach 返回 false,当前路由组件会被销毁,不会触发后续的 store 方法。
3. store
-
触发时机:shouldDetach 返回 true 后,Angular 会调用 store 方法,将当前路由组件实例缓存起来。
-
作用:将当前路由的组件实例存储到一个容器中(例如对象或 Map)。
-
联系:它依赖于 shouldDetach 的返回值,缓存组件实例供后续的 shouldAttach 和 retrieve 使用。
4. shouldAttach
-
触发时机:当切换到目标路由时,判断是否需要从缓存中加载组件实例。
-
作用:返回 true 时,Angular 会调用 retrieve 方法,从缓存中获取组件实例。
联系:如果 shouldAttach 返回 false,Angular 会重新创建目标路由的组件,而不会调用 retrieve。
5. retrieve
-
触发时机:shouldAttach 返回 true 后,Angular 会调用 retrieve 方法,获取缓存的组件实例。
-
作用:从 store 方法保存的缓存中取出组件实例,供路由复用使用。
联系:它依赖于 shouldAttach 的返回值。如果返回 null,Angular 会重新创建目标组件。
流程总结
用户导航 ->
shouldReuseRoute
└── true: 当前路由复用,流程结束
└── false: 路由切换
|
shouldDetach
└── true: 缓存组件 -> 调用 store
└── false: 销毁组件
↓
目标路由 ->
shouldAttach
└── true: 从缓存加载 -> 调用 retrieve
└── false: 创建新组件
方法间的实际联系
- 决定是否缓存的链路:
-
shouldReuseRoute 返回 false → 检查 shouldDetach。
-
如果 shouldDetach 返回 true,则缓存组件实例,并调用 store。
- 决定是否复用的链路:
-
进入目标路由时,检查 shouldAttach。
-
如果 shouldAttach 返回 true,则调用 retrieve 获取缓存实例。
- 缓存与复用的桥梁:
- store 和 retrieve 是缓存组件实例的核心,store 负责存,retrieve 负责取。
- 复用前的终止条件:
- 如果 shouldReuseRoute 返回 true,整个流程提前结束,既不缓存当前组件,也不会加载缓存。
示例:它们如何配合?
假设我们希望缓存 dashboard 路由的组件,流程可能如下:
- 用户离开 dashboard 路由,进入其他路由:
• shouldReuseRoute 返回 false。
• shouldDetach 返回 true,调用 store 缓存组件实例。
- 用户返回 dashboard 路由:
• shouldReuseRoute 返回 false。
• shouldAttach 返回 true,调用 retrieve,从缓存加载组件实例。
总结
• RouteReuseStrategy 的方法不是孤立的,它们形成一个完整的复用逻辑链路。
• shouldDetach 和 store 决定当前组件是否缓存,shouldAttach 和 retrieve 决定目标组件是否从缓存中加载。
• shouldReuseRoute 是一个优先级最高的判断,决定是否完全跳过复用策略。
一般情况下,shouldReuseRoute 方法默认内容如下,一般不需要修改:
shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean {
this.nextRoute = future;
return future.routeConfig === curr.routeConfig;
}