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