【发布时间】:2015-07-15 22:09:53
【问题描述】:
我的 Angular 应用程序面临一些严重的性能问题,这肯定是由于我的 ng-repeat 实施不当,但我不知道如何做得更好。我尝试了其他一些组合,但都没有给我想要的结果,也没有更好的性能。由于异步和 $digest 中止,出现了一些无限循环、未定义的变量。 这就是它应该看起来的样子(所以这是工作结果,但目前还没有优化):http://scr.hu/0ei9/8bpw9
蓝色单元格的天数 = 用户在场,红色单元格 = 不存在。下面是每天的“班次”(每个班次可以在不同的日子完成)。
当我 console.log 一些函数时,它们被调用的次数超出了需要的次数,例如 isPresent(用于检查用户是否提交了可用的日期)被称为 5x180(180可能是 5 个用户 x 每月 30 天)和 getDayOfWeek(在班次行的模板中使用)28+840+812...有 10 个班次。
而我通常只需要为所有单元格调用 isPresent 1x180 并为一个班次行调用一个月中的 1x30 天 getDayOfWeek。也就是说,我真的不明白为什么它被调用了这么多次以及如何优化它。
此外,当我单击蓝色单元格时,会调用 setShift() 函数。我在这里复制了函数但不分析它,我只是想表明它没有调用任何以前的函数,但是我 console.log 令人印象深刻的 28x“星期几”+ 180“存在”和 + 812 “一周中的天”。不知道它来自哪里...坦率地说,我单击的所有内容都称为相同的数量-如果我更改月份,年份,请单击一个独立的按钮...为了更好地阅读代码,我省略了一些类和 css。
感谢您的帮助。
编辑
在注释和取消注释一些代码之后,我发现当我调用 setShift() 函数时,大多数不需要的日志来自最后一个子调用:showPopover(),我在其中打开了一个 $modal。评论时,我看到的只有 1/3。在模态出现之前,剩下的就是这些东西了。此外,我认为 templpateUrl 可能是原因,因为在评论时它没有记录所有数百个“存在”和“星期几”。当我单击模式上的任意位置时,它会调用所有这些功能。有任何想法吗?
JS 角度函数
$scope.isPresent = function(day, month, year, userId) {
console.log('is present')
var date = new Date(year, month - 1, day + 1)
var day = moment(date).format("D-M-YYYY");
for (var i = 0; i < $scope.presences.length; i++) {
var presentDay = moment($scope.presences[i].start).format("D-M-YYYY")
if (presentDay == day && userId == $scope.presences[i].coursierId) {
return true
}
}
}
$scope.getDayOfWeek = function(day, month, year) {
console.log('day of the week')
var date = new Date(parseInt(year), month - 1, day + 1)
var dayId = date.getDay();
return dayId;
}
/*
used for a limited ng-repeat
*/
$scope.getTimes = function(n) {
return new Array(n);
};
/*
Shows a list of sorted out shifts with corresponding
hours, cities and capabilities of coursier.
*/
$scope.setShift = function(day, month, year, userId, event) {
var date = new Date(year, month - 1, day)
var day = moment(date).format("D-M-YYYY");
var dayOfWeek = moment(date).day()
//SORT SHIFTs BY DAY OF WEEK clicked
var day_shifts = $scope.sortShiftByDayOfWeek(dayOfWeek)
//console.log(day_shifts)
//check if the day clicked is an dispo present day
for (var i = 0; i < $scope.presences.length; i++) {
var dispoDay = moment($scope.presences[i].start).format("D-M-YYYY")
//if yes, check the presence user id and the cell of user clicked
if (dispoDay == day) {
//then get all the shifts that fit into this coursier's time range
if ($scope.presences[i].coursierId == userId) {
var dispo = $scope.presences[i];
var dispoHours = $scope.getDispoHoursAndDay(dispo);
var time_shifts = $scope.compareDiposHoursAndShift(dispoHours, day_shifts);
//then sort the shifts by the dispo's and shift's cities
var time_city_shifts = $scope.compareDispoCityAndShift(time_shifts, dispo);
var time_city_able_shifts = $scope.compareUserAndShift(time_city_shifts, userId);
$scope.showPopover(time_city_able_shifts, event);
}
};
};
}
###Calendar table
<table class="table table-bordered">
<!--days of month-->
<tr class="mainHeader">
<th>coursier/jour</th>
##calendar.days = 30 days of month, for example
<th class="monthDay" ng-repeat=" numDay in [] | range: calendar.days">{{$index+1}} {{calendar.daysNames[$index]}}
</th>
</tr>
<!-- user name and days -->
<tr ng-repeat="user in coursiers">
<!-- <td class="coursierName">nom coursier</td> -->
<td>
<a href="#"> {{user.name}}</a>
</td>
<td ng-click="setShift($index+1, monthNum,year, user._id, $event)" ng-repeat="numDay in getTimes(calendar.days) track by $index" ng-class=" isPresent($index, monthNum,year, user._id) == true ?
'present' : isAbsent($index, monthNum,year, user._id) == true ?
'absent' : '' ">
</td>
</tr>
<tr>
<td>Shifts par jour</td>
<td class="shiftsParJourCell" ng-repeat="day in getTimes(calendar.days) track by $index">
<span ng-repeat="shift in shifts">
<span ng-repeat="jour in shift.jours">
{{jour.id ==
getDayOfWeek($parent.$parent.$index, monthNum, year) ? shift.nom : ''}}
</span>
</span>
</td>
</tr>
</table>
【问题讨论】:
-
我会首先在每次视图更改时对视图数据进行预处理,而不是在摘要周期中处理它,从而尽可能多地消除 ng-repeat 中的函数调用。
-
看看this question and its answer。您的视图可能会被多次评估以确认它没有更改,这就是您看到这么多函数调用的原因。根据 Kevin B 的建议,尝试使用直接更新数据的观察者来摆脱方法调用。
-
另外,@ginold,如果你能创建一个 Plunker/jsFiddle,我们或许能提供更好的帮助。没有工作示例就很难优化代码。
-
在 ng-repeat 上使用一次性绑定表达式
::getTimes(calendar.days),在插值上使用{{::,以减少调用(角度 1.3+) -
在注释和取消注释一些代码之后,我发现当我调用 setShift() 函数时,大部分不需要的日志来自最后一个子调用:showPopover() 我打开 $modal .评论时,我看到的只有 1/3。在模态出现之前,剩下的就是这些东西了。此外,我认为 templpateUrl 可能是原因,因为在评论时它没有记录所有数百个“存在”和“星期几”。当我单击模式上的任意位置时,它会调用所有这些功能。有什么想法吗?
标签: javascript angularjs performance optimization ng-repeat