Angular 性能问题、ng-repeat、不需要的回调
Angular performance issues, ng-repeat, unwanted callbacks
我的 angular 应用程序遇到了一些严重的性能问题,这肯定是由于我的 ng-repeat 实施不当,但我不知道如何做得更好。我尝试了其他一些组合,但 none 没有给我想要的结果,也没有更好的性能。由于异步和 $digest 中止,出现了一些无限循环、未定义的变量。
这就是它应该看起来的样子(这就是工作结果,但现在还没有优化):http://scr.hu/0ei9/8bpw9
蓝色单元格的天数 = 用户在场,红色单元格 = 不在。下面是每天的 "shifts"(每个轮班可以在不同的日子完成)。
当我 console.log 某些函数时,它们被调用的次数超出了需要的次数,例如 isPresent (用于检查用户是否将日期提交为可用)被称为 5x180(180 可能是 5 个用户 x 一个月的 30 天)和 getDayOfWeek(在班次行的模板中使用)28+840+812...有 10 个班次.
而我通常只需要为所有单元格调用 isPresent 1x180,为一个班次行调用 getDayOfWeek 1x30 天。也就是说,我真的不明白为什么它被调用了那么多次以及如何优化它。
此外,当我单击蓝色单元格时,会调用 setShift() 函数。我在这里复制了函数但没有分析它,我只是想证明它没有调用任何以前的函数,但是我 console.log 令人印象深刻的 28x "days of the week" + 180 "is present" 和+ 812 "day of the week"。不知道它来自哪里...坦率地说,我点击的所有内容都调用相同的金额 - 如果我更改月份、年份,请单击一个独立按钮...
为了更好地阅读代码,我省略了一些 类 和 css。
感谢您的帮助。
编辑
在对一些代码进行注释和反注释后,我发现当我调用 setShift() 函数时,大部分不需要的日志都来自最后一个子调用:showPopover(),我在其中打开了一个 $modal。评论时,我以前看到的内容只有 1/3。在模态出现之前还有这些东西的其余部分。此外,我认为 temlpateUrl 可能是原因,因为在评论时它不会记录 'is present' 和 'day of week' 的所有那些猎犬。当我点击模态框的任意位置时,它会调用所有这些功能。有任何想法吗?
JS angular 函数
$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>
一段时间后,就我而言,问题是我没有使用指令。
范围有不需要的交互(仍然不知道为什么)但是在 angular 指令中分离我的 html 到目前为止没有问题。
我的 angular 应用程序遇到了一些严重的性能问题,这肯定是由于我的 ng-repeat 实施不当,但我不知道如何做得更好。我尝试了其他一些组合,但 none 没有给我想要的结果,也没有更好的性能。由于异步和 $digest 中止,出现了一些无限循环、未定义的变量。 这就是它应该看起来的样子(这就是工作结果,但现在还没有优化):http://scr.hu/0ei9/8bpw9
蓝色单元格的天数 = 用户在场,红色单元格 = 不在。下面是每天的 "shifts"(每个轮班可以在不同的日子完成)。
当我 console.log 某些函数时,它们被调用的次数超出了需要的次数,例如 isPresent (用于检查用户是否将日期提交为可用)被称为 5x180(180 可能是 5 个用户 x 一个月的 30 天)和 getDayOfWeek(在班次行的模板中使用)28+840+812...有 10 个班次.
而我通常只需要为所有单元格调用 isPresent 1x180,为一个班次行调用 getDayOfWeek 1x30 天。也就是说,我真的不明白为什么它被调用了那么多次以及如何优化它。
此外,当我单击蓝色单元格时,会调用 setShift() 函数。我在这里复制了函数但没有分析它,我只是想证明它没有调用任何以前的函数,但是我 console.log 令人印象深刻的 28x "days of the week" + 180 "is present" 和+ 812 "day of the week"。不知道它来自哪里...坦率地说,我点击的所有内容都调用相同的金额 - 如果我更改月份、年份,请单击一个独立按钮...为了更好地阅读代码,我省略了一些 类 和 css。
感谢您的帮助。
编辑
在对一些代码进行注释和反注释后,我发现当我调用 setShift() 函数时,大部分不需要的日志都来自最后一个子调用:showPopover(),我在其中打开了一个 $modal。评论时,我以前看到的内容只有 1/3。在模态出现之前还有这些东西的其余部分。此外,我认为 temlpateUrl 可能是原因,因为在评论时它不会记录 'is present' 和 'day of week' 的所有那些猎犬。当我点击模态框的任意位置时,它会调用所有这些功能。有任何想法吗?
JS angular 函数
$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>
一段时间后,就我而言,问题是我没有使用指令。 范围有不需要的交互(仍然不知道为什么)但是在 angular 指令中分离我的 html 到目前为止没有问题。