38

我正在尝试将父组件注入子组件。我认为这很简单——只需在子组件中指定/注入父组件constructor()

constructor(private _parent:AppComponent) {}   // child component constructor

我收到以下错误:

例外:无法解析 ChildComponent(?) 的所有参数。确保它们都具有有效的类型或注释。

我错过了什么?

子组件:

import {Component} from 'angular2/core';
import {AppComponent} from './app.component';

@Component({
  selector: 'child',
  template: `<p>child</p>`
})
export class ChildComponent {
  constructor(private _parent:AppComponent) {}
}

应用组件:

import {Component} from 'angular2/core';
import {ChildComponent} from './child.component';

@Component({
  selector: 'my-app',
  template: `{{title}} <child></child>
  `,
  directives: [ChildComponent]
})
export class AppComponent {
  title = "Angular 2 - inject parent";
  constructor() { console.clear(); }
}

普朗克

4

2 回答 2

50

请参阅@EricMartinez 的评论以获取答案。当 A 导入 B 和 B 导入 A 时,问题似乎是循环引用。

这是一个使用两个文件而不是Eric 的 plunker的一个文件的 plunker 。

与我原来的 plunker 的唯一变化是在 ChildComponent 中:

import {Component, Inject, forwardRef} from 'angular2/core';
// ....
constructor(@Inject(forwardRef(() => AppComponent)) private _parent:AppComponent)

我不确定这是否消除了循环引用,因为 A 和 B 仍在相互导入,但它似乎有效。

另请参阅https://github.com/angular/angular/issues/3216,其中 Miško 指出:

这个 [使用 forwardRef() 的非用户友好声明] 是 JS 的限制以及函数声明如何被提升。每当你有一个循环依赖时,你都需要forwardRef:-(我只是看不到它周围的东西。

我认为您不应该处于父母需要了解孩子而孩子需要了解父母的情况。@Query应该处理大多数用例。

很抱歉,虽然我同意这在极少数情况下会很痛苦,但我看不到解决办法,因此这个问题不可行,将关闭。

嗯......我尝试注入父母的原因是因为我看到了孩子与父母交流的两种方式:

  1. 子定义输出属性并发出父订阅的事件
  2. 子级注入父级(例如,Pane 可能会注入 Tabs),然后可以调用父级上的方法

我试图确定何时使用每种方法。Miško 听起来像 2. 应该很少见。

更新:我在想这个更多...... 1.更好,因为孩子和父母之间的耦合较少。1. 孩子不需要知道(也可能不应该知道)父母的公共 API/接口。
在相反的方向(例如,父级使用@ViewChild(@Query现在不推荐使用) 来获取对子级的引用,然后在子级上调用方法),耦合很好,因为父级正在使用子组件,所以它需要知道孩子的公共API/接口:即输入和输出属性和公共方法。

于 2015-12-31T04:06:25.840 回答
9

你可以@Host像这样简单地使用装饰器:

import {Component, Host} from 'angular2/core';
// ....
constructor(@Host() private app: AppComponent)
于 2018-11-20T12:32:55.663 回答