提高嵌套的 ng-repeat + 指令性能 [英] Improving nested ng-repeat + directive performance

查看:26
本文介绍了提高嵌套的 ng-repeat + 指令性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

1) 控制器:根据选择的月/年生成一个包含该月每一天的数组.每当年或月发生变化时,$scope.$watchCollection 都会更新数组.

正如代码解释了我做得更好的地方:

<tr><th><input type="text" ng-model="employeefilter"/></th><th colspan="7" ng-repeat="周中周">{{周 |周刊}}</th></tr><tr><th>&nbsp;</th><th ng-repeat="一天中的一天">{{day.format("ddd")}}</th></tr><tr><th>&nbsp;</th><th ng-repeat="一天中的一天">{{day.date()}}</th></tr><tr ng-repeat="员工在计划中 | 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="赋值"赋值 ng-repeat="赋值中的赋值"assignment-description = "{{assignment.description}}"assignment-period="{{assignment.period}}"assignment-type="{{assignment.type}}">

</td></tr>

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

  1. 今天是公共假期吗?
  2. 员工当天上班吗?
  3. 员工有假期吗?
  4. 获取当天的项目任务

每当员工列表发生变化(由于过滤器)或月份发生变化时,当有大约 40 名员工时,表格的生成最多需要 6 秒.

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

谢谢,如果需要更多信息,请说明.

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

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

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

更新 2: 我意识到我一直在低效地处理这个问题......在查看了范围之后与 batarang 绑定 + 查看代码本身,我注意到我做了太多的getAssignments()"检查,而且我的整个方法都是基于为员工获取分配",而它可能会更好/更快地专注于获得一天的任务.我会在周末更新代码 &如果可以改善/解决问题,请发布答案.

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

更新 4:指令代码:

angular.module('planning.directives', ["templates.app", "ui.bootstrap", "planning.controllers"]).directive("赋值", function () {返回 {限制:EA",替换:真的,范围: {分配数据:=",assignmentCreateMethod: "&"},模板:'<div class="assignment">{{assignmentData.description}}&nbsp;</div>',链接:函数(范围、元素、属性){element.addClass(scope.assignmentData.type);if (scope.assignmentData.period == "am") {element.css("宽度", "50%");element.css("浮动", "左");}if (scope.assignmentData.period == "pm") {element.css("宽度", "50%");element.css("float", "right");}element.on(鼠标输入",函数(){element.addClass("悬停");}).on("mouseleave", function () {element.removeClass("悬停");});element.on("点击", function() {scope.assignmentCreateMethod();});}};});

解决方案

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

I have a horizontal month calendar that shows the activities for employees per day.

Currently it's using a table with the following hierarchy/flow

1) Controller: Generate an array containing every day for that month based on the select month / year. A $scope.$watchCollection updates the array whenever year or month changes.

As the code explains what I do better:

<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>

The problem is that the getAssignments() is "expensive" as it needs to check:

  1. Is it a public holiday?
  2. Does the employee work on that day?
  3. Has the employee a holiday?
  4. Get the project assignments for that day

Whenever the list of employee is changed (due to a filter), or the month changes, the generating of the table takes up to 6 seconds when having ~40 employees.

Is there another way to approach this, or to improve the nesting of ng-repeats?

Thanks, can clarify if more info is needed.

EDIT:

I've tried removing some elements from the code to see what causes improvements. When I let assignments return a dummy value, the rendering improves by 2-3 seconds, so some caching there might help it. However, it still takes 3-4 seconds to render the "empty" table that way.

I've then removed logic from the directive itself, effectively making it empty, this still caused the same delay.

However, when removing the directive itself from the html, the table renders almost instantly when changing dates. Do I have to assume that this is a (normal?) limitation to angular? I don't want static data, as the goal is to drag assignments around.

Update 2: I realised that I've been approaching this pretty inefficiently... After looking at the scopes & bindings with batarang + reviewing the code itself, I've noticed that I'm doing way too much "getAssignments()" checks, and that my entire approach is based on "getting assignments for an employee", while it'll probably be better / faster to focus on getting assignments for a day. I'll update the code over the weekend & post an answer if it improves/resolves the issue.

Update 3: After rewriting the way the planning get generated, it now takes 2 seconds to display the table for 50 resources. There are about 1750 directives, (at least 1 event for an employee per day). I assume this is a normal delay seeing the size?

update 4: Code for directive:

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();
            });
        }
    };
});

解决方案

In this case it sounds like you're rendering a lot more information that would be able to be visible at any one time. So you could:

这篇关于提高嵌套的 ng-repeat + 指令性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆