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