Angular 15:同作用域下同名Token注入值追加问题及解决
Angular多作用域同名Token合并实现方案
需求背景
父作用域通过SOME_TOKEN提供字符串"parent",子作用域提供同名Token(值为"child")时,需将值合并为列表["child", "parent"],且无法修改第三方库代码。
初次尝试:触发循环依赖
最初编写的provideToken函数因直接注入当前Token,触发循环依赖错误:
export const provideToken = (val: string) => { return { provide: SOME_TOKEN, useFactory: () => { const token = inject(SOME_TOKEN) return token ? [...token, val] : val } } }
默认Angular仅返回最近作用域的Token值,曾考虑通过服务在构造函数追加值、ngOnDestroy中移除,但该方式易出错。
优化尝试1:skipSelf导致Token丢失
添加skipSelf配置后,共享模块的"shared"Token被忽略,仅能获取当前模块的"some"Token:
@NgModule({ declarations: [SharedDirective], imports: [], exports: [SharedDirective], providers: [provideToken("shared")] }) export class SharedModule {} @NgModule({ declarations: [SomeComponent], imports: [SharedModule], exports: [], providers: [provideToken("some")] }) export class SomeModule {}
最终解决方案:multi:true + 数组扁平化去重
添加multi:true配置后无Token被忽略,但结果为嵌套数组,因此扩展库指令,在构造函数中扁平化数组并去重:
最终版provideToken函数
export const provideToken = (val: string) => { return { provide: SOME_TOKEN, useFactory: () => { const token = inject(SOME_TOKEN, {skipSelf: true, optional: true}) return token ? [...token, val] : val }, multi: true } }
扩展指令的构造函数处理
// 扩展指令的构造函数 constructor( ..., @Optional() @Inject(SOME_TOKEN) providedToken: MaybeArray<string>, ... ) { if (Array.isArray(providedToken)) { providedToken = [...new Set(providedToken.flat(Infinity))] } super(..., providedToken, ...) }
内容的提问来源于stack exchange,提问作者ertucode
相关产品推荐
相关产品推荐

