自定义RouteReuseStrategy依赖注入困境:登出清缓存遇废弃方法问题
我之前也踩过这个坑!依赖服务的RouteReuseStrategy确实容易因为注入时机或者旧方案里的废弃API卡壳,给你分享一个我亲测有效的实现思路,完全不用那些废弃方法:
解决依赖服务的RouteReuseStrategy登出清缓存问题
核心问题在于RouteReuseStrategy的实例化时机较早,直接在类里注入服务可能会遇到注入顺序问题,而旧方案常用的Injector.get()这类方法已经被废弃。下面是基于依赖注入+RxJS订阅的可靠实现:
1. 自定义RouteReuseStrategy类,通过构造函数注入服务
注意不要直接给RouteReuseStrategy类加@Injectable()装饰器,而是后续通过工厂函数注入依赖,确保服务能正确初始化:
import { RouteReuseStrategy, DetachedRouteHandle, ActivatedRouteSnapshot } from '@angular/router'; import { AuthService } from './auth.service'; import { Subscription } from 'rxjs'; export class CustomRouteReuseStrategy implements RouteReuseStrategy { private cachedRoutes = new Map<string, DetachedRouteHandle>(); private logoutSubscription?: Subscription; constructor(private authService: AuthService) { // 订阅登出事件,触发缓存清除 this.logoutSubscription = this.authService.logout$.subscribe(() => { this.clearAllCachedRoutes(); }); } // 决定是否复用当前路由 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return future.routeConfig === curr.routeConfig; } // 决定是否存储当前路由缓存 shouldDetach(route: ActivatedRouteSnapshot): boolean { // 可自定义缓存规则,比如通过路由data里的reuse字段判断 return route.data?.reuse === true; } // 存储路由缓存 store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { const routeKey = this.generateRouteKey(route); this.cachedRoutes.set(routeKey, handle); } // 决定是否恢复缓存的路由 shouldAttach(route: ActivatedRouteSnapshot): boolean { const routeKey = this.generateRouteKey(route); return this.cachedRoutes.has(routeKey); } // 获取缓存的路由实例 retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { const routeKey = this.generateRouteKey(route); return this.cachedRoutes.get(routeKey) || null; } // 生成唯一的路由标识key,避免不同路由缓存冲突 private generateRouteKey(route: ActivatedRouteSnapshot): string { return route.routeConfig?.path || JSON.stringify(route.params); } // 清除所有缓存路由 private clearAllCachedRoutes(): void { this.cachedRoutes.clear(); } }
2. 在AppModule中用工厂函数提供策略,确保依赖注入正确
不要用useClass直接声明,而是通过useFactory+deps的方式创建实例,这是Angular当前版本推荐的依赖注入方式:
import { NgModule } from '@angular/core'; import { RouteReuseStrategy } from '@angular/router'; import { CustomRouteReuseStrategy } from './custom-route-reuse-strategy'; import { AuthService } from './auth.service'; @NgModule({ providers: [ AuthService, { provide: RouteReuseStrategy, useFactory: (authService: AuthService) => new CustomRouteReuseStrategy(authService), deps: [AuthService] // 声明需要注入的依赖服务 } ] }) export class AppModule { }
3. 确保AuthService中的登出事件是可观察对象
在你的认证服务里定义一个Subject,当用户执行登出操作时触发事件:
import { Injectable } from '@angular/core'; import { Subject } from 'rxjs'; @Injectable({ providedIn: 'root' }) export class AuthService { // 登出事件流 logout$ = new Subject<void>(); logout(): void { // 执行实际登出逻辑(比如清除token、跳转登录页) localStorage.removeItem('authToken'); this.logout$.next(); } }
关键注意事项
- 避免使用旧方案中的
Injector.get()等废弃API,useFactory+deps的方式能完美解决依赖注入顺序问题 - 记得在RouteReuseStrategy中取消订阅登出事件(如果策略是单例可忽略,但加上更稳妥),避免内存泄漏
- 路由缓存的key要保证唯一,建议结合路由path和参数生成,防止不同路由复用同一缓存
这个方案我在Angular 14+版本中多次使用,完全没有问题,也避开了废弃API的坑。
内容的提问来源于stack exchange,提问作者ricksmt
相关产品推荐
相关产品推荐

