通过自定义注入器将服务注入动态生成的组件时,Angular ChangeDetection 不起作用
Posted
技术标签:
【中文标题】通过自定义注入器将服务注入动态生成的组件时,Angular ChangeDetection 不起作用【英文标题】:Angular ChangeDetection not working when injecting services via custom injector into dynamically generated components 【发布时间】:2021-10-08 22:32:15 【问题描述】:由于我没有找到任何答案或类似案例,所以我在这里发布这个问题。
我的应用具有以下结构:
应用模块 布局模块 主要组件 侧边栏组件 SidebarService providedIn: 'root' 内容模块 内容组件 ContentService providedIn: 'ContentModule' ContentSidebarComponent 另一个模块 另一个组件 AnotherService providedIn: 'AnotherModule' 另一个边栏组件ContentModule 和 AnotherModule 风格的模块还有很多。
SidebarComponent 内部是一个用于动态组件生成的视图容器。
SidebarService 包含一个类似 generateSidebar(component: any): void
的方法,它在 ContentComponent:generateSidebar(ContentSidebarComponent)
和 AnotherComponent:generateSidebar(AnotherSidebarComponent)
内部调用,并像这样处理动态组件加载:
带有自定义注入器的动态组件加载器
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(...);
const viewContainerRef = viewContainer.viewContainerRef;
viewContainerRef.clear();
let componentRef: ComponentRef<any>;
let injector: Injector|undefined = undefined;
injector = Injector.create(
providers: [
provide: ContentService, //AnotherService respectively
useClass: ContentService, //AnotherService respectively
deps: []
]
)
componentRef = viewContainerRef.createComponent(
componentFactory,
0,
injector
);
没有像“No provider for ...”这样的错误。
访问 ContentComponent 时,会在 SidebarComponent 内部正常生成 ContentSidebarComponent。
访问AnotherComponent时,在SidebarComponeent内部正常生成AnotherSidebarComponent。
问题 ContentService 也在 ContentComponent 内部使用,并且 ContentService 的一些属性发生了变化。似乎 ChangeDetection 在 ContentSidebarComponent 中不起作用,因为 ContentService 的属性在那里没有改变。
顺便说一句:如果有多个实例,两个服务都会抛出错误。所以这不是这种情况,也不是问题。
当注入服务的属性值发生变化时,如何在动态生成的组件内触发 ChangeDetection?
提前致谢。
【问题讨论】:
您确定问题出在变更检测上吗?添加一个按钮以将您认为已更改的值记录到控制台,并查看它是否真的发生了变化。 我在服务中添加了一个属性,可以通过一个按钮进行更改。按钮,它的点击方法在 ContentComponent 中。服务中的属性会发生变化,就像在 ContentComponent 的模板中一样,但在 ContentSidebarComponent 的模板中没有 好吧...好像有2个实例,构造函数被触发了两次...如何避免这种情况?如何注入服务? angular.io/guide/… 似乎使用useExisting
而不是 useClass
是解决方案......但这给了我对 ContentService 的循环依赖
【参考方案1】:
修复了它像这样将服务实例传递给提供者
public generateComponent(component: any, service: any, instance: any)
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(component);
const viewContainerRef = viewContainer.viewContainerRef;
viewContainerRef.clear();
let componentRef: ComponentRef<any>;
let injector: Injector|undefined = undefined;
injector = Injector.create(
providers: [
provide: service,
useValue: instance,
deps: []
]
)
componentRef = viewContainerRef.createComponent(
componentFactory,
0,
injector
);
【讨论】:
以上是关于通过自定义注入器将服务注入动态生成的组件时,Angular ChangeDetection 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
Angular 2 - 如何将依赖项注入到自定义类中,该类不是组件并且不作为服务公开
Android 组件化路由组件 ( 页面跳转参数依赖注入 )
.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法