Как улучшить мой Angular Ng-repeat и остановить замораживание страницы?

#angularjs #laravel-5

#angularjs #laravel-5

Вопрос:

Я использую angular для отображения моего приложения регистрации посещаемости. Мне нужно было отобразить таблицу с командами и связанными с ней пользователями вместе с данными о посещаемости. Я использовал ng-repeat для рендеринга таблицы, используя следующий код, но таблица зависает, когда я пытаюсь применить какие-либо фильтры или даже когда я пытаюсь загрузить ее нормально. Пожалуйста, помогите.

Вид блейда Laravel

 <div class="table-responsive" ng-show="!loading">
                <table class="table table-bordered text-center" ng-repeat="team in teamsAndAttendances | filter: { 'id': teamFilter }:true track by $index">
                    <tr>
                        <th class="active text-center" colspan="100%">@{{ team.name }}</th>
                    </tr>
                    <tr>
                        <th class="text-center info">Day</th>
                        <th class="text-center" ng-repeat="weekDay in weekDays track by $index" ng-class="getDayStringClass(weekDay)">@{{ weekDay | amDateFormat: 'ddd' }}</th>
                    </tr>
                    <tr>
                        <th class="text-center info">Date/Engineer</th>
                        <th class="text-center active" ng-repeat="weekDay in weekDays track by $index">@{{ weekDay | amDateFormat: 'DD-MM-YYYY' }}</th>
                    </tr>
                    <tr ng-repeat="user in team.users">
                        <th class="text-center active">@{{ user.name }}</th>
                        <td 
                            ng-repeat="day in getNumberOfDays(weekDays.length) track by $index"
                            ng-bind="getAttendanceByDate(weekDays[$index],user.id)"
                            id="attData" 
                        ></td>
                    </tr>
                </table>
 

Угловой контроллер

 function AttendanceCtrl($scope,LeavesAndAttendancesFactory,moment,$resource) {

var vm = $scope;

vm.plClass = false;

vm.loading = false;

vm.teamsAndAttendances = [];

vm.attendanceObject = {};

LeavesAndAttendancesFactory.getTeamsUsersAttendances().query().$promise.then(function(res) {
    return vm.teamsAndAttendances = res;
});

vm.getNumberOfDays = function(days) {
    return new Array(days);
}

vm.getAttendanceByDate = function(dateStamp,userID) {

    var fetchedDate = moment(dateStamp).format('YYYY-MM-DD');

    var users = angular.forEach(vm.teamsAndAttendances, function(team) {
        return team.users;
    });

    console.log(users);
}

vm.getAttendanceClass = function(plClass) {
    if(plClass)
    {
        return 'danger';
    } else {
        return 'active';
    }
}

vm.loadTeams = function() {
    return $resource('../api/teams/all').query().$promise.then(function(data) {
        vm.teams = data;
    });
}

vm.getDayStringClass = function(dateStamp) {
    var day = moment(dateStamp).format('ddd');
    if(day === 'Sat' || day === 'Sun')
    {
        return 'light-fire';
    } else {
        return 'info';
    }
}

var today = moment();

vm.weekDays = [];

var startOfWeek = moment().startOf('week');
var endOfWeek = moment().endOf('week');

var day = startOfWeek;

while (day <= endOfWeek) {
    vm.weekDays.push(day.toDate());
    day = day.clone().add(1, 'd');
}
 

}

Комментарии:

1. Вы создаете свои данные на лету в шаблоне. Перенос всего этого на контроллер должен ускорить процесс. Я рекомендую вам подготовить все данные в контроллере и позволить шаблону отображать только данные без всех вызовов функций, таких как getAttendanceByDate и т. Д

2. @osi Есть какие-нибудь идеи о том, как этого добиться? Я здесь немного потерялся.

3. Сделайте то же самое, что и в вашем шаблоне, но вместо написания логики в вашем шаблоне используйте циклы for в вашем контроллере.

4. @osi большое спасибо. Попробую сделать это прямо сейчас.

Ответ №1:

Избегайте использования filters with ng-repeat .
Ng-repeat с фильтром повлияет на производительность страницы, как указано в документе.

Попробуйте отфильтровать данные в самом контроллере или службе и ng-repeat с уже отфильтрованными данными.

И используйте ng-bind вместо {{ }} .

Например :

 app.controller("controllerName", function(){
    $scope.allData = [1,2,3,4];
    $scope.filteredData = [];

    $scope.filterData(){
        var data = [];
        data = _.filter($scope.allData, function(a){
            if(a > 3){
                return a;
            }       
        });

        $scope.filteredData = data;
    }

    $scope.filterData();
});


<div ng-repeat = "item in filteredData" >
    <span ng-bind="item"></span>
</div>
 

Демонстративно этот подход решит вашу проблему.

Ответ №2:

Может быть, вы можете попробовать плагин быстрого повтора. https://github.com/gradecam/angular-fast-repeat . Также вы можете попробовать одноразовую привязку: https://toddmotto.com/angular-one-time-binding-syntax /