如何在自定义Angular Router Reuse Strategy类中注入服务跟踪已分离组件?
解决方案
在Angular中,自定义RouteReuseStrategy类确实无法直接通过构造函数注入依赖(因为它由框架实例化),但可以通过以下两种方式注入你的组件跟踪服务:
方式一:使用Angular inject函数(Angular 14+)
这是最简洁的方案,利用Angular 14引入的inject函数可以直接在类属性中获取服务实例,无需构造函数处理:
1. 先创建组件跟踪服务
import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class ComponentTrackingService { // 存储已分离的组件实例 detachedComponents: any[] = []; // 添加跟踪逻辑 trackDetachedComponent(componentInstance: any) { this.detachedComponents.push(componentInstance); // 可添加去重、日志等额外逻辑 } // 其他所需方法,比如获取所有分离组件、清除列表等 }
2. 自定义路由复用策略类
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; import { inject } from '@angular/core'; import { ComponentTrackingService } from './component-tracking.service'; export class CustomRouteReuseStrategy implements RouteReuseStrategy { // 直接用inject获取服务实例 private trackingService = inject(ComponentTrackingService); // 用于存储路由句柄的缓存 private routeCache = new Map<string, DetachedRouteHandle>(); // 实现RouteReuseStrategy的必要方法 shouldReuseRoute(future: ActivatedRouteSnapshot, curr: ActivatedRouteSnapshot): boolean { return future.routeConfig === curr.routeConfig; } shouldAttach(route: ActivatedRouteSnapshot): boolean { return this.routeCache.has(route.routeConfig?.path || ''); } retrieve(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { return this.routeCache.get(route.routeConfig?.path || '') || null; } shouldDetach(route: ActivatedRouteSnapshot): boolean { // 根据你的需求决定是否缓存路由,这里示例为所有路由都缓存 return !!route.routeConfig?.path; } store(route: ActivatedRouteSnapshot, handle: DetachedRouteHandle): void { const path = route.routeConfig?.path || ''; this.routeCache.set(path, handle); } // 关键:在detach方法中跟踪分离的组件 detach(route: ActivatedRouteSnapshot): DetachedRouteHandle | null { const handle = this.routeCache.get(route.routeConfig?.path || ''); if (handle) { // 获取组件实例并传给跟踪服务 this.trackingService.trackDetachedComponent(handle.componentRef.instance); // 可选:如果不需要保留缓存,可以移除 // this.routeCache.delete(route.routeConfig?.path || ''); } return handle || null; } }
3. 在模块中注册自定义策略
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { CustomRouteReuseStrategy } from './custom-route-reuse.strategy'; import { AppComponent } from './app.component'; @NgModule({ imports: [BrowserModule, /* 你的路由模块等 */], declarations: [AppComponent], providers: [ { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } ], bootstrap: [AppComponent] }) export class AppModule {}
方式二:使用静态Injector引用(兼容低版本Angular)
如果你的项目版本低于Angular 14,可以通过静态保存Injector实例的方式获取服务:
1. 修改自定义路由复用策略类
import { RouteReuseStrategy, ActivatedRouteSnapshot, DetachedRouteHandle } from '@angular/router'; import { Injector } from '@angular/core'; import { ComponentTrackingService } from './component-tracking.service'; export class CustomRouteReuseStrategy implements RouteReuseStrategy { private static injector: Injector; private trackingService: ComponentTrackingService; private routeCache = new Map<string, DetachedRouteHandle>(); // 静态方法用于设置Injector static setInjector(injector: Injector) { CustomRouteReuseStrategy.injector = injector; } constructor() { // 通过Injector获取服务实例 this.trackingService = CustomRouteReuseStrategy.injector.get(ComponentTrackingService); } // 其余RouteReuseStrategy方法实现同方式一,detach方法逻辑一致 }
2. 在AppModule中初始化Injector
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { CustomRouteReuseStrategy } from './custom-route-reuse.strategy'; import { Injector } from '@angular/core'; import { AppComponent } from './app.component'; @NgModule({ imports: [BrowserModule, /* 你的路由模块等 */], declarations: [AppComponent], providers: [ { provide: RouteReuseStrategy, useClass: CustomRouteReuseStrategy } ], bootstrap: [AppComponent] }) export class AppModule { constructor(injector: Injector) { // 初始化静态Injector CustomRouteReuseStrategy.setInjector(injector); } }
关键说明
- 在
detach方法中,我们从DetachedRouteHandle的componentRef.instance获取到组件实例,这是跟踪分离组件的核心入口。 - 你可以根据业务需求调整
shouldDetach方法的逻辑,决定哪些路由的组件需要被跟踪。
内容的提问来源于stack exchange,提问作者Mark
相关产品推荐
相关产品推荐

