javascript - AngularJS ng-repeat 性能和基准测试

标签 javascript angularjs performance angularjs-ng-repeat

我正在测试 AngularJS 的性能,以确定它是否适合我们的应用程序。为了衡量和比较 DOM 创建的速度,我创建了一个 JSFiddle example人们可以在这里玩弄不同数量的元素来创造。

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

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 也是如此,它也会创建自己的子作用域。

这是一个修改后的 fiddle ,其中 ng-if 和 ng-switch 已被删除: http://jsfiddle.net/2z2e33em/

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

关于javascript - AngularJS ng-repeat 性能和基准测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28215797/

相关文章:

javascript - 如何在 Express.js 中共享 Controller 之间的通用逻辑?

javascript - js中给对象添加属性

javascript - 从 nginclude 调用父作用域上的函数

c++ - 为什么一个子线程的执行时间比整个应用程序的执行时间多

mySQL 效率问题 - 如何找到规范化的正确平衡...?

javascript - 如何将内部 JavaScript 文件链接到 GitHub 中的 HTML 文件

javascript - 如何使用赋值而不是设置值?

javascript - 使用 Controller 中定义的范围进行 ng 过滤

angularjs - 获取 ItemID Office.context.mailbox.item.itemId outlook mac os 插件

performance - ui-performance 插件无法在开发模式下工作 (Grails)