Angular组件能否查看模块层级?共享组件如何判断所属模块?
共享组件能否识别自身所属的渲染模块?
假设存在如下路由与模块结构:
// 根路由配置 const routes: Routes = [ { path: '', canMatch: [ () => inject(AGuard).canMatch() ], loadChildren: () => import('./a.module').then(m => m.AModule), }, { path: '', canMatch: [ () => inject(BGuard).canMatch() ], loadChildren: () => import('./b.module').then(m => m.BModule), }, ]; // AModule @NgModule({ imports: [ARoutingModule], providers: [], }) export class AModule {} // BModule @NgModule({ imports: [BRoutingModule], providers: [], }) export class BModule {} // A模块路由 const aRoutes: Routes = [ { path: 'somewhere', component: SomeComponent }, ]; @NgModule({ imports: [RouterModule.forChild(aRoutes)], exports: [RouterModule], }) export class ARoutingModule {} // B模块路由 const bRoutes: Routes = [ { path: 'elsewhere', component: SomeOtherComponent }, ]; @NgModule({ imports: [RouterModule.forChild(bRoutes)], exports: [RouterModule], }) export class BRoutingModule {}
当SomeComponent和SomeOtherComponent都使用同一个共享组件时,该共享组件可以通过以下几种方式确定自己是由AModule还是BModule渲染的:
方法一:注入模块标记服务
创建一个抽象标记类,在两个模块中分别提供不同的实现,共享组件通过注入该服务来区分所属模块:
// 抽象标记类 export abstract class ModuleIdentifier { readonly moduleName: string; } // 在AModule中提供标记 @NgModule({ imports: [ARoutingModule], providers: [ { provide: ModuleIdentifier, useValue: { moduleName: 'AModule' } as ModuleIdentifier } ], }) export class AModule {} // 在BModule中提供标记 @NgModule({ imports: [BRoutingModule], providers: [ { provide: ModuleIdentifier, useValue: { moduleName: 'BModule' } as ModuleIdentifier } ], }) export class BModule {} // 共享组件中使用 @Component({...}) export class SharedComponent { constructor(private moduleId: ModuleIdentifier) { console.log(`当前所属模块:${this.moduleId.moduleName}`); } }
方法二:通过路由信息推断
由于两个模块对应不同的路由路径(somewhere和elsewhere),共享组件可以注入ActivatedRoute来获取当前路由的路径信息,进而判断所属模块:
@Component({...}) export class SharedComponent { constructor(private activatedRoute: ActivatedRoute) { // 获取完整路由路径 const fullPath = this.activatedRoute.snapshot.pathFromRoot .map(segment => segment.url.join('/')) .filter(Boolean) .join('/'); if (fullPath.includes('somewhere')) { console.log('当前由AModule渲染'); } else if (fullPath.includes('elsewhere')) { console.log('当前由BModule渲染'); } } }
方法三:直接注入模块实例(不推荐)
可以将模块本身作为提供者注入,共享组件通过尝试注入不同模块来判断,但这种方式需要处理注入失败的情况,不够优雅:
// 在AModule中注册自身 @NgModule({ imports: [ARoutingModule], providers: [ { provide: AModule, useExisting: AModule } ], }) export class AModule {} // 在BModule中注册自身 @NgModule({ imports: [BRoutingModule], providers: [ { provide: BModule, useExisting: BModule } ], }) export class BModule {} // 共享组件中判断 @Component({...}) export class SharedComponent { constructor(private injector: Injector) { try { this.injector.get(AModule); console.log('当前由AModule渲染'); } catch (e) { try { this.injector.get(BModule); console.log('当前由BModule渲染'); } catch (e) { console.log('不属于目标模块'); } } } }
内容的提问来源于stack exchange,提问作者patrick
相关产品推荐
相关产品推荐

