我有一个看起来有点像这样的组件层次结构:
@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”。每次从websocket接收数据时,serviceThatDeliversData都会创建DataItem列表。然后将此列表传递给'B',其中每个列表条目用作子组件的基础('C',我省略了C组件,因为它基本上只显示输入数据'项')。
我现在的问题如下: 由于每次服务获得更新时列表都会更改,因此新创建了C组件+ B组件的完整列表。我假设因为DataItem列表完全改变Angular将它们注意为新条目(?)而列表作为新条目本身(?) 但实际上很可能只添加或删除了一个项目,或者其中一个项目中的字段已更改。因此,只需要删除/添加/更新一个C组件。
由于这种情况,任何C组件视图中发生的任何动画都会在重新创建列表后停止并重新开始。加上我想避免的一些其他副作用。
所以我的问题是,有没有办法让Angular只更新与内部实际更改的DataItem相关的C组件以及添加到列表中或从列表中删除的C组件,但保留那些没有改变了吗?
我已经搜索了一段时间,发现可以使用changeDetection:ChangeDetectionStrategy.OnPush,但是我没有找到一个可以帮助解决我的问题的工作示例(使用更改数组和更改数组元素(内部))。
我假设可以在“B”中存储列表的副本,手动检查更改然后对它们作出反应 - 这也可以通过动画来完成,以通知用户哪个条目被删除或添加 - 但是需要一种方法来阻止Angular更新(重新创建)'B'和'C'组件。我使用相同的数组(清除它并用新条目重新填充它)可能有效。
但我仍然想知道这是否可以通过原始的Angular机制实现。
答案 0 :(得分:1)
更改检测策略OnPush
仅获取使用Input
- 装饰器修饰的值的更改,并且仅在值的引用更改时才会更改。
例如,myArray[1] = 'a';
只会改变数组并且不会创建新的引用,因此使用OnPush
策略的角度将无法获取更改。您必须克隆数组并进行更改以创建新的数组引用。
您在ngForOf
指令中重新创建元素的问题在我的另一个answer中有所描述。阅读答案末尾的注释。