【发布时间】:2017-10-08 22:39:37
【问题描述】:
我得到了一个看起来有点像这样的组件层次结构:
@Component({
...
})
export class A {
constructor(private _serviceThatDeliversData: Service){}
getData(): Array<DataItem> {
return this._serviceThatDeliversData.getData();
}
}
html:
<b-selector [data]="getData()"></b-selector>
子组件:
@Component({
selector: 'b-selector'
...
})
export class B {
@Input() data: Array<DataItem>;
}
html:
<ul>
<li *ngFor="let item of data">
<c-selector [item]="item"></c-selector>
</li>
</ul>
所以我得到了一个从服务接收数据的父组件“A”。 serviceThatDeliversData 每次从 websocket 接收数据时都会创建 DataItem 列表。然后将该列表传递给“B”,其中每个列表条目都用作子组件的基础(“C”,我在这里省略了 C 组件,因为它基本上只显示输入数据“项目”)。
我现在的问题如下: 由于每次服务更新时列表都会更改,因此新创建了 C 组件 + B 组件的整个列表。我假设因为 DataItem 列表完全改变了,Angular 将它们视为新条目(?)并将列表本身作为新条目(?) 然而,实际上很可能只添加或删除了一项,或者其中一项中的一个字段发生了变化。所以只需要删除/添加/更新一个 C 组件。
因此,在任何 C 组件的视图中发生的任何动画都会停止并在重新创建列表后重新开始。再加上我想避免的其他一些副作用。
所以我的问题是,有没有办法让 Angular 只更新与内部实际更改的 DataItem 相关的 C 组件以及在列表中添加或删除的 C 组件,但保留未更新的组件原封不动地改了?
我已经搜索了一段时间,发现可以使用 changeDetection: ChangeDetectionStrategy.OnPush,但是我还没有找到可以帮助我解决问题的有效示例(使用更改数组和更改数组元素(内部))。
我假设可以将列表的副本存储在“B”中,手动检查更改然后对它们做出反应 - 这也可以通过动画来完成,以向用户指示删除或添加了哪个条目 - 但是这样会需要一种方法来完全阻止 Angular 更新(重新创建)“B”和“C”组件。我使用相同的数组(清除它并用新条目重新填充它)可能会起作用。
但我仍然想知道这是否可以通过原始 Angular 机制实现。
【问题讨论】:
标签: arrays angular typescript angular2-changedetection