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

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

问题描述

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



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



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



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

 < table class =table table-bordered table-condensedng-controller =PlanningOverviewController> 
< tr>
< th>< input type =textng-model =employeefilter/>< / th>
< th colspan =7ng-repeat =以周为单位的周>
{{周| 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 =员工在计划中|过滤器:employeefilter>
< td> {{employee.firstName}} {{employee.lastName}}< / td>
< td class =calendar-unitng-repeat =day in daysng-init =assignments = getAssignments(day,employee)>
< div class =assignment
assignment ng-repeat =赋值转让
assignment-description ={{assignment.description}}
assignment-period ={{assignment.period}}
assignment-type ={{assignment.type}}>

< / div>
< / td>
< / tr>
< / table>

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


  1. 这是公众假期吗?

  2. 员工当天是否工作?

  3. 员工是否有假期?

  4. 获取当天的项目作业

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



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



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



编辑:



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



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



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



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



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



更新4:指令代码:

  angular.module('planning.directives',[templates.app,ui.bootstrap,planning.controllers])
.directive (赋值,函数(){
返回{
restrict:EA,
替换:true,
范围:{
assignmentData:=,
assignmentCreateMethod:&
},
模板:'< div class =assignment> {{assignmentData.description}}& nbsp;< / div>' ,
link:function(scope,element,attrs){

element.addClass(s​​cope.assignmentData.type);

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

if(scope.assignmentData.period ==pm){
elem ent.css(宽度,50%);
element.css(float,right);
}

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

element.on(click,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天全站免登陆