在Angular 2中,子组件可以通过构造函数参数获取其父组件。例如:
@Component({...})
export class ParentComponent {
...
}
@Component({...})
export class ChildComponent {
constructor(private parent: ParentComponent) { }
...
}
只要父母和孩子的类型不同,这种方法很有效。
然而,另一个典型用例是树结构,其中每个树节点显示为单独的组件。如果每个树节点组件都应该有权访问其父节点,我们该怎么办?我试过这个:
@Component({...})
export class TreeNodeComponent {
constructor(private parent: TreeNodeComponent) { }
...
}
但是由于以下运行时异常而失败:
EXCEPTION: Cannot instantiate cyclic dependency!
我想原因是Angular 2注入组件本身而不是其父组件。
即使它们属于同一类型,我如何告诉angular注入一个组件的父组件?
答案 0 :(得分:20)
这种方式正在运作
constructor(@SkipSelf() @Host() @Optional() parent: TreeNodeComponent) {}
@SkipSelf()
如果请求TreeNodeComponent
则不会自行注入@Host()
看起来不比主持人元素@Optional()
??根节点TreeNodeComponent
答案 1 :(得分:0)
Angular2查看提供者的当前注入器。在您的情况下,TreeNodeComponent对应于组件本身。
父组件实例位于父注入器中。
我认为你可以尝试注入一个Injector类来访问父注入器,然后获取父组件的实例。这样的事情:
@Component({
(...)
})
export class TreeNodeComponent {
constructor(injector:Injector) {
let parentInjector = injector.parent;
let parent = patentInjector.get(TreeNodeComponent);
}
}
有关Injector类的文档,请参阅此链接:
那就是说,我认为Gunter关于绑定和共享服务的评论特别相关......
答案 2 :(得分:0)
感谢Günther,这篇文章已经解决了。但是,我想根据我得到的架构反馈进行跟进。
首先:我完全同意TreeNodeComponent用例示例是反模式。像树这样的数据驱动组件应该通过数据绑定来控制。我为这种反模式道歉。
但是,我的实际用例(解释起来比较复杂)是我想开发一个高级下拉菜单。要求:
用法示例:
<dropdown label="Actions">
<dropdown-item label="Action 1" (click)="action1()"></dropdown-item>
<dropdown-item label="Action 2" (click)="action2()"></dropdown-item>
<dropdown-item label="Submenu">
<dropdown-item label="Action 3.1" (click)="action31()"></dropdown-item>
<dropdown-item label="Action 3.2">
<dropdown-slider (change)="changeHandler()"></dropdown-slider>
</dropdown-item>
<dropdown-item label="Submenu">
<dropdown-item label="Action 3.3.1" (click)="action331()"></dropdown-item>
<dropdown-item label="Action 3.3.2" (click)="action332()"></dropdown-item>
</dropdown-item>
</dropdown-item>
</dropdown>
我的考虑是使用数据绑定很难实现。能够绑定事件处理程序并以这种方式包含自定义组件非常实用。
但我可能错了!对此非常欢迎!