嵌套ng内容的父注入器无法正常工作



使用<ng-content></ng-content>进行内容投影时,通常可以通过依赖项注入访问父组件:

@Component({
selector: 'app-parent',
template: 'Parent / <ng-content></ng-content>'
})
export class ParentComponent {}
@Component({
selector: 'app-child',
template: 'Child / Has parent: {{parentComponent != null}}'
})
export class ChildComponent {
constructor(@Optional() public parentComponent: ParentComponent) {}
}
<app-parent>
<app-child></app-child>
</app-parent>
<!-- this will output Parent / Child / Has parent: true -->

然而,当添加另一层时,这似乎不起作用,尽管app-parent仍然是DOM中app-child的直接父级:

@Component({
selector: 'app-host',
template: `Host / <app-parent><ng-content></ng-content></app-parent>`
})
<app-host>
<app-child></app-child>
</app-host>
<!-- this will output: Host / Parent / Child / Has parent: false -->

另请参阅此stackblitz以获取示例:https://stackblitz.com/edit/angular-ivy-e7c6i8?file=src/app/app.component.html

即使在嵌套场景中,是否有某种方法可以从ChildComponent访问ParentComponent

这将不起作用,因为ChildComponent正被投影为HostComponent的内容。因此,在层次注入器的眼中,ChildComponentParentComponent是兄弟姐妹,因为它们都是HostComponent的孩子。

您可以通过使用forwardRef使HostComponent成为ParentComponent的提供者并在适当的生命周期挂钩中分配值来绕过它,但如果这样做有效的话,至少可以说是粗略的,因为在依赖组件中注入时,引用的实际值将为空。

基本上,尝试直接访问父组件是一种糟糕的做法,您应该尽量避免这种情况。相反,使用@Input/@Output进行子级和父级之间的通信。如果有很多逻辑在进行,您可以创建一个单独的服务(它可以是单例的,即在应用程序级别上提供,也可以由其他组件提供,例如ParentComponent,因此范围为一个父子对(

最新更新