改进嵌套的ng-repeat +指令性能

Bus*_*ata 7 performance html-table angularjs angularjs-ng-repeat

我有一个横向月历,显示每天员工的活动.

目前它正在使用具有以下层次结构/流的表

1)控制器:根据选定的月/年生成包含该月每天的数组.$ scope. $ watchCollection每年或每月更改时都会更新数组.

由于代码解释了我做得更好:

<table class="table table-bordered table-condensed" ng-controller="PlanningOverviewController">
    <tr>
        <th><input type="text" ng-model="employeefilter"/></th>
        <th colspan="7" ng-repeat="week in weeks">
            {{week | weekheader}}
        </th>
    </tr>
    <tr>
        <th>&nbsp;</th>
        <th ng-repeat="day in days">
            {{day.format("ddd")}}
        </th>
    </tr>
    <tr>
        <th>&nbsp;</th>
        <th ng-repeat="day in days">
            {{day.date()}}
        </th>
    </tr>
    <tr ng-repeat="employee in planning | filter:employeefilter">
        <td> {{employee.firstName}} {{employee.lastName}}</td>
        <td class="calendar-unit" ng-repeat="day in days" ng-init="assignments = getAssignments(day, employee)">
            <div class="assignment"
                 assignment  ng-repeat="assignment in assignments"
                 assignment-description = "{{assignment.description}}"
                 assignment-period="{{assignment.period}}"
                 assignment-type="{{assignment.type}}">

            </div>
        </td>
    </tr>
</table>
Run Code Online (Sandbox Code Playgroud)

问题是getAssignments()是"昂贵的",因为它需要检查:

  1. 这是公众假期吗?
  2. 员工当天工作吗?
  3. 员工有假期吗?
  4. 获取当天的项目作业

无论何时更改员工列表(由于过滤器)或月份更改,当拥有约40名员工时,生成表最多需要6秒.

有没有其他方法来解决这个问题,或者改进ng-repeats的嵌套?

谢谢,可以澄清是否需要更多信息.

编辑:

我已经尝试从代码中删除一些元素,看看是什么导致了改进.当我让赋值返回一个虚拟值时,渲染会提高2-3秒,因此一些缓存可能会有所帮助.但是,以这种方式呈现"空"表仍需要3-4秒.

然后,我从指令本身中删除了逻辑,实际上使其为空,这仍然导致相同的延迟.

但是,从html中删除指令本身时,表格在更改日期时几乎立即呈现.我是否必须假设这是对角度的(正常?)限制?我不想要静态数据,因为目标是拖动分配.

更新2:我意识到我一直在接近这个非常低效的...在查看范围和绑定与batarang +审查代码本身后,我注意到我做得太多了"getAssignments()"检查并且我的整个方法都是基于"为员工分配",而专注于获得一天的任务可能会更好/更快.我将在周末更新代码并在答案改进/解决问题后发布答案.

更新3:重写计划生成方式后,现在需要2秒钟才能显示50个资源的表.大约有1750条指令(每天至少有一名员工参加).我认为这是看到大小的正常延迟?

更新4:指令代码:

angular.module('planning.directives', ["templates.app", "ui.bootstrap", "planning.controllers"])
  .directive("assignment", function () {
    return {
        restrict: "EA",
        replace: true,
        scope: {
            assignmentData: "=",
            assignmentCreateMethod: "&"
        },
        template: '<div class="assignment">{{assignmentData.description}}&nbsp;</div>',
        link: function (scope, element, attrs) {

            element.addClass(scope.assignmentData.type);

            if (scope.assignmentData.period == "am") {
                element.css("width", "50%");
                element.css("float", "left");
            }

            if (scope.assignmentData.period == "pm") {
                element.css("width", "50%");
                element.css("float", "right");
            }

            element.on("mouseenter",function () {
                element.addClass("hover");
            }).on("mouseleave", function () {
                    element.removeClass("hover");
                });

            element.on("click", function() {
                scope.assignmentCreateMethod();
            });
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

Mic*_*mza 2

在这种情况下,听起来您正在渲染更多可以随时可见的信息。所以你可以:

  • 重新考虑使用某种分页的界面,这样您在任何时候都只能呈现一屏信息。或者可能对您一次可以显示的周数进行限制。

  • 创建某种指令,ngIf如果其内容在屏幕上不可见,则删除其内容(即通过 )。也许监听窗口上的(去抖的)滚动事件,并调用http://verge.airve.com/中的函数来测试它的任何部分是否可见。在这种情况下,整理元素的垂直尺寸可能很棘手,因此这稍微取决于您的用例。

    澄清一下,这必须在 Angular 渲染内容之前删除内容,而不仅仅是隐藏元素。