ngFor 如何工作?
当ngFor
循环的列表发生变化时, ngFor
会尽量避免完全重构列表的DOM元素。许多DOM元素会被重用, 这些元素的一些属性值可能会改变。
ngFor
默认跟踪列表元素的方式是使用对象标识。这就意味着如果你使用一个和原来列表内容完全一样的新对象, 把新对象传到ngFor
,angular是没办法辨别这个对象是不是已经存在的。从对象标识的角度来说,新的列表包含一套全新的内容, 跟原来的列表完全不一样。因为angular不知道应该用什么属性来跟踪对象的变化, 所以这种默认方式是合理的。
弊端:
-
在列表很大的情况下(或者列表占了屏幕的很大一部分时), 用这种默认的方式会导致页面加载很慢(很多DOM要被销毁重建)
-
如果列表被重新加载, 加载完成后滚动条会跑到列表底部(对用户不友好)
使用 trackBy
使用trackBy
我们可以自己定义ngFor
的跟踪机制。首先我们要在ngFor
里给trackBy
传一个函数, 这个函数有两个默认参数(名称可以自己起),如:
-
index
当前循环到的对象的索引 -
item
当前循环到的对象
栗子:
@Component({
selector: 'heroes',
template:`
<table>
<thead>
<th>Name</th>
</thead>
<tbody>
<tr *ngFor="let hero of heroes; trackBy: trackHero" >
<td>{{hero.name}}</td>
</tr>
</tbody>
</table>
`
})
export class Heroes {
heroes = HEROES;
trackHero(index, hero) {
console.log(hero);
return hero ? hero.id : undefined;
}
}
上面这个例子会使用hero的id属性作为ngFor跟踪列表的依据。使用trackBy可以避免上文中的两个使用ngFor默认跟踪机制的弊端。