AngularJS ng-repeat Performance & Benchmark

AngularJS ng-repeat Performance & Benchmark

本文关键字:Benchmark amp ng-repeat Performance AngularJS      更新时间:2023-09-26

我正在测试AngularJS的性能,以确定它是否适合我们的应用程序。为了测量和比较 DOM 创建的速度,我创建了一个 JSFiddle 示例,可以在其中使用不同数量的项目来创建。

目标是显示其项目排序的 n 个随机用户。有基于项目类型的内容,如果用户是秘密的,则根本不应该显示他。

.HTML:

<div ng-repeat="user in users | orderBy:'project'" post-repeat-directive
     ng-if="user.secretagent == false"
     class="user"
     ng-class="{male: (user.gender == 'm'), female: (user.gender != 'm')}"
     ng-switch="user.project">
    <h2>{{user.name}}</h2>
    Project: {{user.project}}
    <em ng-switch-when="fame">[fame]</em>
    <em ng-switch-when="idol">[idol]</em>
</div>

Javascript:

    angular.module('AngularBench', [])
    .config(['$compileProvider', function ($compileProvider) {
        $compileProvider.debugInfoEnabled(false);
    }])
    .controller("benchmarkController", ['$scope', 'TimeTracker', function($scope, TimeTracker) {
        $scope.result = undefined;
        $scope.users = [];
        $scope.benchmark = function(size) {
            TimeTracker.clockStartDate(size);
            var users = getUsers(size);
            $scope.users = users;
            $scope.$watch(
                    function () {   return TimeTracker.getDuration(); }, 
                    function(newVal, oldVal) { $scope.result = newVal; }, 
                    true
            );
        };
    }])
    .factory('TimeTracker', function() {
        var start, end, duration;
        return {
            clockStartDate: function() {
                start = Date.now();
            },
            clockEndDate: function() {
                end = Date.now();
                duration = (end - start) / 1000;
            },
            getDuration: function() {
                return duration;
            }
        };
    })
    .directive('postRepeatDirective', ['$timeout', 'TimeTracker', function($timeout, TimeTracker) {
        return function(scope, element, attrs) {
            if (scope.$last){
                $timeout(function(){
                    TimeTracker.clockEndDate();
                });
            }
        };
    }]);
function getUsers(size) {
    var users = [];
    for (var i=0; i<size; i++) {
        var user = {
            name: 'User ' + i,
            gender: Math.random() > 0.5 ? 'm' : 'w',
            project: Math.random() > 0.25 ? 'fame' : 'idol',
            secretagent: Math.random() > 0.95
        };
        users.push(user);
    }
    return users;
}

但是,我注意到随着项目数量的增加,性能会大幅下降。在大约 2500 个项目时,它真的太慢了

我知道常见的建议是使用分页或自动滚动,但这并不是要找到ngRepeat中大列表的替代解决方案。您对提高性能有什么建议吗?

如果您打算对数千个项目进行 ng-repeat,那么您将无法回避这样一个事实,即您必须格外注意并尽可能多地优化每次迭代。

例如,可以优化隐藏用户的逻辑。您可以使用过滤器删除不应显示的用户,而不是使用 ng-if :

ng-repeat="user in users | filter:usersFilter | orderBy:'project'"

这样,我们可以更早地删除它们(甚至在我们对用户进行排序之前)。这比每次迭代都必须初始化指令要快得多,特别是因为 ng-if 创建了一个新的子作用域,这有点昂贵。

ng-switch也是如此,它也创建了自己的子范围。

这是一个修改的小提琴,其中ng-if和ng-switch已被移除:http://jsfiddle.net/2z2e33em/

它产生相同的最终结果,而且它更快也就不足为奇了,因为我们现在已经删除了两个指令。但我认为它说明了这样的变化如何对性能产生巨大影响(修改后的小提琴对我来说大约快 3 倍)。