Knockout foreach vs Angular ng-repeat

What I did with Knockout, and I'm trying to do with Angular.

In my current project, I have a table whose data is added by a scroll event. When the user scrolls down, I add 20 rows to the end of the table, and the total number of rows can reach 2 to 10 thousand. I start showing 20 records, and when the user scrolls down, I continue to add 20 rows until the total number of rows is reached.

As in the Angular script example, when replay is used, if new data is placed in the Angular array, all records are executed and rendered again, but the knockout only executes and displays the new record added. In my project, because I show thousands of data in one table in a way that Angular works, or I think it works, kills my performance.

Only a few weeks have passed when I use Angular. I dont know. If I do something wrong or I need to change some things.

Knockoutjs example :

<h2>Your seat reservations</h2> <table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Test</th> </tr></thead> <tbody data-bind="foreach: seats()"> <tr> <td data-bind="text: mealName"></td> <td data-bind="text: price"></td> <td data-bind="text: $root.cellAdded()"></td> </tr> </tbody> </table> <button data-bind="click: $root.PushData()">I am Here</button> 

JS:

 // Overall viewmodel for this screen, along with initial state function ReservationsViewModel() { var self = this; self.cellAdded = function(){ console.log('Test Added'); return 'ok'; }; self.PushData = function(){ console.log('PushData Called'); self.seats.push({ mealName: "Standard (sandwich)", price: 0 }); }; // Editable data self.seats = ko.observableArray([ { mealName: "Standard (sandwich)", price: 0 }, { mealName: "Premium (lobster)", price: 34.95 }, { mealName: "Ultimate (whole zebra)", price: 290 } ]); } ko.applyBindings(new ReservationsViewModel()); 

AngularJS example :

 <div ng-app> <div ng-controller="TodoCtrl"> <h2>Your seat reservations</h2> <table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Test</th> </tr></thead> <tbody > <tr ng-repeat="seat in seats"> <td>{{seat.mealName}}</td> <td>{{seat.price}}</td> <td>{{callMe()}}</td> </tr> </tbody> </table> <button ng-click="addRow()">Add Row</button> </div> </div> 

JS:

 function TodoCtrl($scope) { $scope.callMe = function(){ console.log('Test Added'); return 'Yes'; }; // initialize controller model $scope.seats = [ { mealName: "Standard (sandwich)", price: 0 }, { mealName: "Premium (lobster)", price: 34.95 }, { mealName: "Ultimate (whole zebra)", price: 290 } ]; // Define member functions $scope.addRow = function() { console.log('PushData Called'); $scope.seats.push( { mealName: "Standard (sandwich)", price: 0 }); }; } 
+8
angularjs
source share
1 answer

I suggest upgrading to Angular 1.3+ and using its one-time binding feature, given that the records do not change after adding. This minimizes the clock on your DOM by a good amount and helps increase productivity.

 <div ng-app> <div ng-controller="TodoCtrl"> <h2>Your seat reservations</h2> <table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Test</th> </tr></thead> <tbody > <tr ng-repeat="seat in seats"> <td>{{::seat.mealName}}</td> <td>{{::seat.price}}</td> <!--<td>{{callMe()}}</td>--> </tr> </tbody> </table> <button ng-click="addRow()">Add Row</button> </div> </div> 

I also recommend removing this function call in your expression, as it evaluates the Angular digest cycle every time, which is a real performance killer.

If you want to check if your model has been updated, use $ watch in your controller ( https://docs.angularjs.org/api/ng/type/ $ rootScope.Scope).

 $scope.$watch('seats', function() { console.log('Test Added'); }); 

One more hint, not yet related to performance: this is good practice and helps to minimize problems with the area so that you always use some kind of model object in your controllers. So your controller will look like this:

 function TodoCtrl($scope) { // initialize controller model $scope.model = {}; $scope.model.seats = [ { mealName: "Standard (sandwich)", price: 0 }, { mealName: "Premium (lobster)", price: 34.95 }, { mealName: "Ultimate (whole zebra)", price: 290 } ]; // Define member functions $scope.addRow = function() { console.log('PushData Called'); $scope.model.seats.push( { mealName: "Standard (sandwich)", price: 0 }); }; $scope.$watch('model.seats', function() { console.log('Test Added'); }); } 

and your HTML:

 <div ng-app> <div ng-controller="TodoCtrl"> <h2>Your seat reservations</h2> <table> <thead><tr> <th>Passenger name</th><th>Meal</th><th>Test</th> </tr></thead> <tbody > <tr ng-repeat="seat in model.seats"> <td>{{::seat.mealName}}</td> <td>{{::seat.price}}</td> <!--<td>{{callMe()}}</td>--> </tr> </tbody> </table> <button ng-click="addRow()">Add Row</button> </div> </div> 

Also, as @Gabe mentioned, ngInfiniteScroll could be a good addition to your use case: http://binarymuse.imtqy.com/ngInfiniteScroll/

+1
source share

All Articles