ngFor 指令是否会在每次突变时重新渲染整个数组?

Does ngFor directive re-render whole array on every mutation?

假设我们有一组项目:

items = [
    { title: 'item 1'},
    { title: 'item 2'},
    /* ... */
];

并且有一个呈现此数组的模板:

<ul>
    <li *ngFor="let item of items">{{item.title}}</li>
</ul>

如果我通过 push/splice add/remove 项目,angular2 将重新呈现整个数组,还是只会 add/remove 相应项目的标记?如果它只更新,那么突变策略有什么不同——我应该更喜欢 push/splice 而不是数组替换吗?换句话说,这两种方法在渲染性能上是否等效:

/* 1: mutation */
this.items.push({ title: 'New Item' });

/* 2: replacement */
var newArray = this.items.slice();
newArray.push({ title: 'New Item' });

this.items = newArray;

没有,它re-renders只有当数组本身被不同的数组实例替换时。

更新

感谢 Olivier Boissé(查看评论)

即使传递了不同的数组实例,Angular 也会识别它是否包含相同的项目实例并且即使在那时也不会重新呈现。

另请参阅此 StackBlitz example

如果使用的 IterableDiffer 识别并在开头或中间添加或删除,则一个项目在那个地方是 inserted/removed 而没有 re-rendering 所有其他项目。

Plunkers 在回答这个问题时展示的动画 How can I animate *ngFor in angular 2? 也证明了这一点。事实上,这种动画是以这种方式实现的驱动因素(除了一般优化)

除了 Gunter 的回答之外,如果您想知道 UI 的哪一部分是 rendered/re-rendered,您可以使用 Chrome(甚至独立于任何 lib/framework) :

  • 打开你的调试面板
  • 菜单(调试面板)/更多工具/渲染

然后您应该会看到以下面板:

打开 Paint Flashing 选项,享受您的列表带来的乐趣。
如果某个区域呈绿色闪烁,则表示它已被绘制 / re-painted .

EX:如果您在 Gunter 的回答中使用 Plunkr:http://plnkr.co/edit/oNm5d4KwUjLpmmu4IM2K?p=preview 并打开 Paint Flashing,将一个项目添加到列表中,您将看到之前的项目不会闪烁。 (这意味着没有重绘)。