AngularJs 的 ng-repeat 讓咱們很是方便的遍歷數組生成 Dom 元素,可是使用不當也會有性能問題。數據庫
在項目中咱們使用 ng-repeat 加載完一個列表後,若是再次請求數據,而後過濾列表,代碼可能會這麼寫:數組
<div ng-controller="Test"> <button ng-click="request()">請求新數據</button> <div ng-repeat="user in users"> {{user.name}} </div> </div>
Controller 的代碼:緩存
app.controller('Test', function($scope) { var users = []; for (var i = 0; i < 100; i++) { users[i] = { id: i, name: "User: " + i }; } $scope.users = users; $scope.request = function () { // 從服務器加載新數據 var result = []; // 直接從新賦值給 users $scope.users = result; }; });
查看 ng-repeat 的源碼能夠發現,當 ng-repeat 的數組被替換時, 它默認並不會從新利用已有的 Dom 元素,而是直接將其所有刪除並從新生成新的數組 Dom 元素:服務器
// 將上次生成的全部 dom 移除 for (key in lastBlockMap) { if (lastBlockMap.hasOwnProperty(key)) { block = lastBlockMap[key]; elementsToRemove = getBlockElements(block.clone); $animate.leave(elementsToRemove); forEach(elementsToRemove, function(element) { element[NG_REMOVED] = true; }); block.scope.$destroy(); } }
Dom 的頻繁操做是很是不友好的,爲何 ng-repeat 不能利用已有的 dom 元素去更新數據呢?由於你沒有把數組元素的標識屬性告訴它,那麼兩次替換的時候它就沒辦法追蹤了,咱們能夠看到 ng-repeat 往數組裏每一個元素加了一個 $$hashKey 的屬性:app
這個 key 是由 Angular 內部的 nextUid() 方法生成,相似數據庫自增,可是是使用字符串。dom
如今咱們明白了,由於每次替換數組都會致使 ng-repeat 爲每一個元素生成一個新 key, 因此根本沒辦法重用已有的 Dom 元素,那麼咱們可使用下邊的語法來避免這個問題:性能
<div ng-controller="Test"> <button ng-click="request()">請求新數據</button> // 使用 track by 標識 <div ng-repeat="user in users track by user.id"> {{user.name}} </div> </div>
這樣 ng-repeat 就用將其緩存起來啦,固然可能你的數組元素沒有一個標識屬性,若是元素數量很少那麼能夠接受,否則仍是建議你手動爲其生成一個標識屬性。code