AngularJs ng-repeat 必須注意的性能問題

原文http://www.cnblogs.com/MigCoder/p/3930264.html

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 的屬性:

key

這個 key 是由 Angular 內部的 nextUid() 方法生成,類似數據庫自增,但是是使用字符串。

現在我們明白了,因爲每次替換數組都會導致 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 就用將其緩存起來啦,當然可能你的數組元素沒有一個標識屬性,如果元素數量不多那麼可以接受,不然還是建議你手動爲其生成一個標識屬性。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章