使用 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>
自从 Angular 2 接受了 one-way 数据流范式,我认为 "most 'Angular' way" 解决这个问题是 而不是 完全调用 update()
方法。 child 组件的状态应由 parent.
提供
每当点击发生时,新状态应该在 App
(parent) 组件中计算并传递给 ChildComponent
.
按照这种方式,您将需要通过额外的 属性(例如 clicked
)扩展 parent 中的状态:
rowList = [{name: "Alice", clicked: false}, ...];
(当然,因为undefined
和false
有相同的逻辑值,所以显式声明并不是真正必要的。)
单击时,在处理程序方法中计算新状态。在这种情况下,它只是一个简单的布尔值更改:
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
我可以想出一些方法来解决这个问题,但我想要一些关于最 '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>
自从 Angular 2 接受了 one-way 数据流范式,我认为 "most 'Angular' way" 解决这个问题是 而不是 完全调用 update()
方法。 child 组件的状态应由 parent.
每当点击发生时,新状态应该在 App
(parent) 组件中计算并传递给 ChildComponent
.
按照这种方式,您将需要通过额外的 属性(例如 clicked
)扩展 parent 中的状态:
rowList = [{name: "Alice", clicked: false}, ...];
(当然,因为undefined
和false
有相同的逻辑值,所以显式声明并不是真正必要的。)
单击时,在处理程序方法中计算新状态。在这种情况下,它只是一个简单的布尔值更改:
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