Angular 2 Redux在NgFor中不断重新渲染

时间:2017-06-15 14:33:17

标签: angular memoization ngrx ngrx-store

我在我的项目中使用NGRX,并且不断重新渲染组件时遇到问题。 Store每次产生全新的对象,如果存储数据相同,我不想重新渲染我的组件。我将演示组件的更改检测更改为ChangeDetectionStrategy.OnPush lodash memoization(_.memoization),但它不起作用

商店状态

export interface CardsState {
    cardsA: CardA[];
    cardsB: CardB[];
    cardsC: CardC[];
}

然后将Store状态映射到结构

const entities = [{
 cards: {
  cardsB: [
   {}
  ]
 }
}];

每当商店通过来自lodash的memoize进行更改时,尝试阻止重新呈现cardsB项目

export const memoizeCardBFunc = _.memoize((cardB: CardB): CardB => {
  return _.cloneDeep(cardB);
}, (cardB: CardB) => cardB.entityType + cardB.entityId);

在我的智能组件中,我有下一个HTML

<div *ngFor="let entity of entities | async">
    <div *ngFor="let cardB of entity.cards.cardsB">
        <card-b [cardStateModel]="cardB"></card-b>
    </div>
</div>

令我惊讶的是,它正确适用于一个ngFor,但如果我有两个ng,那它就不起作用了!

<div *ngFor="let cardB of entity.cards.cardsB">
    <card-b [cardStateModel]="cardB"></card-b>
</div>

我已经花了2天时间,它正在杀了我,拜托,求助!

我不是英语母语人士,对不起错误。

谢谢!

2 个答案:

答案 0 :(得分:1)

在For循环中使用trackBy。它将跟踪状态,何时更改数据,而不是触发重新渲染。

    <div *ngFor="let cardB of entity.cards.cardsB;let i = index; trackBy: trackByFn">
        <card-b [cardStateModel]="cardB"></card-b>
    </div>

trackByFn(index, item) {
    return index; // or item.id
  }

阅读以下文档,您将了解更多。 https://v2.angular.io/docs/ts/latest/api/common/index/NgFor-directive.html

答案 1 :(得分:1)

如果你有:

<div *ngFor="let outer of outers">
    <div *ngFor="let inner of outer.inners">
       {{ inner }}
    </div>
</div>

然后,如果outer在某个时刻发生变化,则内部ngFor将重新渲染,这就是您从ngOnInit看到警报的原因。但是,如果将trackBy添加到外部ngFor,并将其识别为相同的元素,则可以避免内部列表重新呈现,这是您当前的问题。

内部trackBy仅保留内部元素并防止重新创建内部元素。外部trackBy保留外部元素,这使内部元素也有机会被保留。