简体   繁体   English

Angular 2变化检测阵列

[英]Angular 2 Change Detection Arrays

I got a component hierarchy that looks a bit like this: 我有一个看起来像这样的组件层次结构:

@Component({
...
})
export class A {

  constructor(private _serviceThatDeliversData: Service){} 

  getData(): Array<DataItem> {
    return this._serviceThatDeliversData.getData();
  }
}

html: HTML:

<b-selector [data]="getData()"></b-selector>

Child component: 子组件:

@Component({
  selector: 'b-selector'
  ...
})
export class B {
  @Input() data: Array<DataItem>;
}

html: HTML:

<ul>
  <li *ngFor="let item of data">
    <c-selector [item]="item"></c-selector>
  </li>
</ul>

So I got a parent component 'A' that receives data from a service. 因此,我得到了一个从服务接收数据的父组件“ A”。 The serviceThatDeliversData creates the DataItem list every time it receives data from a websocket. 每次从WebSocket接收数据时,serviceThatDeliversData都会创建DataItem列表。 This list is then passed down to 'B' where every list entry is used as a base for sub components ('C', I omitted the C component here cause it basically just presents the input data 'item'). 然后将此列表向下传递到“ B”,其中每个列表条目均用作子组件的基础(“ C”,我在这里省略了C组件,因为它基本上只显示输入数据“ item”)。

My problem now is the following: Since the list changes every time the service gets an update, the whole list of C components + the B component is newly created. 现在我的问题是:由于每次服务更新时列表都会更改,因此将重新创建C组件+ B组件的整个列表。 I assume because the DataItem list changes completely Angular notices them as new entries (?) and the list as a new one itself (?) However in reality it might very well be that only one item was added or removed or just a field has changed in one of the items. 我认为是因为DataItem列表完全更改了,所以Angular注意到它们是新条目(?),列表本身是新条目(?)。但是实际上,很可能是仅添加或删除了一项,或者仅更改了一个字段在其中一项中。 So only one C component would needed to be removed/added/updated. 因此,只需要删除/添加/更新一个C组件。

Since that is the case any animations happening in the view in any of the C components stop and start again once the list is recreated. 由于这种情况,一旦重新创建列表,任何C组件中的视图中发生的所有动画都会停止并再次开始。 That plus some other side effects I would like to avoid. 加上其他一些我想避免的副作用。

So my question is, is there a way to let Angular only update the C components which relate to a DataItem that actually changed internally AND the ones that were added or removed to/from the list, but leave the ones that have not changed untouched? 所以我的问题是,有没有办法让Angular仅更新与内部实际更改过的DataItem相关的C组件以及添加到列表或从列表中删除的C组件,而使那些未更改的组件保持不变?

I have searched for a while and found that one could use changeDetection: ChangeDetectionStrategy.OnPush, however I have not found a working example (with a changing array and changing array elements (internally)) that would help me with my problem. 我搜索了一会儿,发现可以使用changeDetection:ChangeDetectionStrategy.OnPush,但是我还没有找到一个可以解决我问题的有效示例(具有不断变化的数组和不断变化的数组元素(内部))。

I assume one could store a copy of the list in 'B', check the changes manually and then react to them - which could also be done with an animation to signal the user which entry was removed or added - however that would require a way to stop Angular from updating (recreating) 'B' and the 'C' components at all. 我假设可以将列表的副本存储在“ B”中,手动检查更改,然后对它们做出反应-这也可以通过动画来完成,以向用户发出信号,指出删除或添加了哪个条目-但是,这需要一种方法完全阻止Angular更新(重新创建)“ B”和“ C”组件。 I take it using the same array (clearing it and repopulating it with the new entries) might work. 我使用相同的数组(将其清除并用新条目重新填充)可能起作用。

But I'd still like to know if this could be possible via raw Angular mechanisms. 但是我仍然想知道是否可以通过原始的Angular机制来实现。

The changedetection strategy OnPush only picks up changes to values decorated with the Input -decorator and only if the reference of the value changes. 更改检测策略OnPush仅在Input的值发生更改时才拾取对使用Input -decorator装饰的值的更改。

For example myArray[1] = 'a'; 例如myArray[1] = 'a'; only mutates the array and no new reference is created, therefore angular with OnPush strategy wouldn't pick up the change. 仅更改数组且未创建新引用,因此使用OnPush策略进行角度操作不会更改。 You have to clone the array and make the change to create a new array reference. 您必须克隆数组并进行更改以创建新的数组引用。

Your problem with angular recreating the elements inside an ngForOf directive is descriped in another answer of me. 我的另一个答案描述了您在ngForOf指令中重新创建元素的角度问题。 Read the note at the end of the answer. 阅读答案末尾的注释。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM