角度2变化检测阵列

时间:2017-10-08 22:39:38

标签: arrays angular typescript angular2-changedetection

我有一个看起来有点像这样的组件层次结构:

@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机制实现。

1 个答案:

答案 0 :(得分:1)

更改检测策略OnPush仅获取使用Input - 装饰器修饰的值的更改,并且仅在值的引用更改时才会更改。

例如,myArray[1] = 'a';只会改变数组并且不会创建新的引用,因此使用OnPush策略的角度将无法获取更改。您必须克隆数组并进行更改以创建新的数组引用。

您在ngForOf指令中重新创建元素的问题在我的另一个answer中有所描述。阅读答案末尾的注释。