ngFor 指令是不是会在每个突变上重新渲染整个数组?
Posted
技术标签:
【中文标题】ngFor 指令是不是会在每个突变上重新渲染整个数组?【英文标题】:Does ngFor directive re-render whole array on every mutation?ngFor 指令是否会在每个突变上重新渲染整个数组? 【发布时间】:2017-07-03 20:05:27 【问题描述】:假设我们有一个项目数组:
items = [
title: 'item 1',
title: 'item 2',
/* ... */
];
还有一个模板可以渲染这个数组:
<ul>
<li *ngFor="let item of items">item.title</li>
</ul>
如果我通过push
/splice
添加/删除项目,Angular2 会重新渲染整个数组,还是只会添加/删除相应项目的标记?如果它只更新,那么突变状态有什么不同——我应该更喜欢推送/拼接而不是数组替换吗?换句话说,这两种方法在渲染性能方面是否等效:
/* 1: mutation */
this.items.push( title: 'New Item' );
/* 2: replacement */
var newArray = this.items.slice();
newArray.push( title: 'New Item' );
this.items = newArray;
【问题讨论】:
【参考方案1】:除了 Gunter 的回答之外,如果您想知道 UI 的哪一部分被渲染/重新渲染,您可以使用 Chrome(甚至独立于任何库/框架):
打开调试面板 菜单(调试面板)/更多工具/渲染然后您应该会看到以下面板:
打开Paint Flashing
选项,享受您的列表的乐趣。
如果某个区域呈绿色闪烁,则它已被涂漆/重新涂漆 ?。
EX:如果您在 Gunter 的回答中使用 Plunkr:http://plnkr.co/edit/oNm5d4KwUjLpmmu4IM2K?p=preview 并打开 Paint Flashing
,将一个项目添加到列表中,您会看到之前的项目不会闪烁。 (这意味着没有重绘)。
【讨论】:
【参考方案2】:没有,只有当数组本身被不同的数组实例替换时才会重新渲染。
更新
感谢 Olivier Boissé(参见 cmets)
即使传递了不同的数组实例,Angular 也会识别它是否包含相同的项目实例并且即使在那时也不会重新渲染。
另见StackBlitz example
如果使用的IterableDiffer
在开头或中间识别并添加或删除,则在该位置插入/删除一个项目,而不重新渲染所有其他项目。
Plunkers 在回答这个问题How can I animate *ngFor in angular 2? 中演示的动画也证明了这一点。事实上,这种动画是以这种方式实现的驱动因素(除了一般优化之外)
【讨论】:
Angular 不会重新渲染前一个数组实例中存在的元素。 @OlivierBoissé 这就是我的回答想要表达的意思。当数组实例被具有相同内容的不同实例替换时,我很确定它将完全重新渲染,否则,正如您所说,它将仅渲染添加的项目并保留 DOM 元素之前的数组。 事件带有一个新实例,它没有完全重新渲染,我通过探索 DOM 对其进行了测试,我有一个 new 数组并且项目没有重新渲染,因为它们之前已经在那儿了 @OlivierBoissé 你没有机会复制stackblitz.com 的例子吗? https://stackblitz.com/edit/angular-dncqm2,检查前两个<p>
你会发现它们没有重新渲染以上是关于ngFor 指令是不是会在每个突变上重新渲染整个数组?的主要内容,如果未能解决你的问题,请参考以下文章
自动列出当前 Object 数据迭代的每个属性值的动态表组件(ngFor 指令);