使用 NgFor 创建 child 个组件,然后调用发出事件的方法

Create child components with NgFor then call a method of whichever emits an event

我可以想出一些方法来解决这个问题,但我想要一些关于最 'Angular' 方法的建议。

我整理了 an example of what I'm doing.

主要组件使用 NgFor 遍历列表并创建一堆 child 组件。
每个 child 在被选中时发出一个事件上升 parent。每个 child 也有一个方法 update().

我想要的是我的主要组件获取对任何 child 发出事件并调用其 update() 方法的引用的正确方法。

看起来很简单(可能很简单),但它是我正在构建的应用程序的核心功能,所以我想尽可能地把它做得漂亮干净。

为你的帮助干杯

最简单的方法是使用模板变量来引用子组件:

<my-child #child *ngFor="let row of rowList;" [id]="row.name"
          (onMD)="processClick($event); child.update()"></my-child>

已更新演示:http://plnkr.co/edit/zA80iNsLHHULGx9Rbffw?p=preview

自从 Angular 2 接受了 one-way 数据流范式,我认为 "most 'Angular' way" 解决这个问题是 而不是 完全调用 update() 方法。 child 组件的状态应由 parent.

提供

每当点击发生时,新状态应该在 App (parent) 组件中计算并传递给 ChildComponent.

按照这种方式,您将需要通过额外的 属性(例如 clicked)扩展 parent 中的状态:

rowList = [{name: "Alice", clicked: false}, ...];

(当然,因为undefinedfalse有相同的逻辑值,所以显式声明并不是真正必要的。)

单击时,在处理程序方法中计算新状态。在这种情况下,它只是一个简单的布尔值更改:

processClick(id){
  this.recentClick = id;
  // Create the new array for immutability benefits.
  this.rowList = this.rowList.map(person => {
    if (person.name === id) {
      return {name: person.name, clicked: true};
    } else {
      return person;
    }
  })
}

该值被传递给 child,与任何其他 @Input 一样。

<my-child *ngFor="let row of rowList;" [id]=row.name [clicked]=row.clicked (onMD)="processClick($event)"></my-child>

现在,child 组件可以根据 clicked 属性 的值更改其行为。作为奖励,当使用不可变数据时,您可以将更改检测策略更改为 onPush for some performance benefits.

@Component({
    // ...
    changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent {
  @Input() clicked: boolean;

  get prefix() {
    return this.clicked ? "Bye!" : "Hi";
  }
  // ...
}

这种方法有很多好处。

  • 您没有潜伏在 child 组件中的隐藏状态。 Parent的"word"是绝对的(所谓的"single source of truth")。
  • parent 并不真正需要知道或关心 children 对数据做了什么或何时需要更新。
  • 您可以轻松地在其他地方提取数据,并且您不需要编写任何代码来使 update() 行为有效。

完整的实现如下所示:http://plnkr.co/edit/IP8iLKxKGCjHOdgPHJ0h?p=preview