ng-repeat
directive, and the other with the use of filters.
ng-repeat
directive starts to work slowly if the two-way binding to lists with more than 2500 elements is implemented. You can read more about this in the post Misko Hevery . This is due to the fact that in AngularJS, changes are tracked by the “dirty check” method. Each change tracking will take some time, which for large lists with a complex data structure results in slowing down your application.
ng-repeat
using its $last
property. The base date is stored in our TimeTracker
service, so the result does not depend on downloading data from the server.
// angular.module('siApp.services').directive('postRepeatDirective', ['$timeout', '$log', 'TimeTracker', function($timeout, $log, TimeTracker) { return function(scope, element, attrs) { if (scope.$last){ $timeout(function(){ var timeFinishedLoadingList = TimeTracker.reviewListLoaded(); var ref = new Date(timeFinishedLoadingList); var end = new Date(); $log.debug("## DOM : " + (end - ref) + " ms"); }); } }; } ]);
<tr ng-repeat="item in items" post-repeat-directive>…</tr>
limitTo
filter (starting with version 1.1.4) and our startFrom
filter. This approach allows to reduce the display time by limiting the size of the displayed list. This is the most effective way to reduce display time.
// $scope.currentPage = 0; $scope.pageSize = 75; $scope.setCurrentPage = function(currentPage) { $scope.currentPage = currentPage; } $scope.getNumberAsArray = function (num) { return new Array(num); }; $scope.numberOfPages = function() { return Math.ceil($scope.displayedItemsList.length/ $scope.pageSize); }; // startFrom angular.module('app').filter('startFrom', function() { return function(input, start) { return input.slice(start); };
<!-- --> <button ng-repeat="i in getNumberAsArray(numberOfPages()) track by $index" ng-click="setCurrentPage($index)">{{$index + 1}}</button <!-- --> <tr ng-repeat="item in displayedItemsList | startFrom: currentPage * pageSize | limitTo:pageSize" /tr>
ng-hide
to hide unnecessary list items.
ng-repeat
evaluates all expressions on each $ digest loop, i.e. this is done very often. In our example, filteredItems()
returns a filtered collection. If it is slow, it will quickly slow down the entire application.
<li ng-repeat="item in filteredItems()"> <!--, .--> <li ng-repeat="item in items"> <!-- -->
filteredLists
variable represents the collection cache, and the applyFilter
method applyFilter
responsible for matching.
/* */ // var items = [{name:"John", active:true }, {name:"Adam"}, {name:"Chris"}, {name:"Heather"}]; // $scope.displayedItems = items; // var filteredLists['active'] = $filter('filter)(items, {"active" : true}); // $scope.applyFilter = function(type) { if (filteredLists.hasOwnProperty(type){ // $scope.displayedItems = filteredLists[type]; } else { /* */ } } // $scope.resetFilter = function() { $scope.displayedItems = items; }
<button ng-click="applyFilter('active')"> </button> <ul><li ng-repeat="item in displayedItems">{{item.name}}<li></ul>
ng-if
disables the display (unlike ng-show
). In this case, additional elements are added, and bindings are resolved exactly when they are needed.
<li ng-repeat="item in items"> <p> {{ item.title }} </p> <button ng-click="item.showDetails = !item.showDetails">Show details</buttons> <div ng-if="item.showDetails"> {{item.details}} </div> </li>
ng-mouseenter
caused the screen to flicker. The frame rate in the browser was in most cases below 30 frames per second. Using pure jQuery to create animation effects and hover effects will help solve this problem. Don't forget to just wrap mouse events with the jQuery.live () function — to receive notifications from elements added to the DOM later.
ng-repeat
directive, each filter returns a subset of the original collection. AngularJS also removes filter-excluded elements from the DOM, and raises the $destroy
event, which also removes them from $scope
. When the input collection changes, the subset of elements passing through the filter also changes, which again causes their redrawing or destruction.
ng-show
and ng-hide
directives. Calculate the filters in the controller and add a property for each element. Use ng-show
with the value of this property. As a result, the ng-hide
directive will simply add a specific class, instead of removing items from a subset of the original collection, $scope
and DOM.
ng-show
is to use the expression syntax. The ng-show
expression is evaluated using the built-in filter syntax.
<input ng-model="query"></input> <li ng-repeat="item in items" ng-show="([item.name] | filter:query).length">{{item.name}}</li>
ng-show
, and further calculations, based on the transferred value, in a separate subcontroller. This method is somewhat more complicated, but its application is more pure, which Ben Nadel justifies in his blog article .
/* */ // 350 . $scope.$watch('queryInput', function(newValue, oldValue) { if (newValue === oldValue) { return; } $debounce(applyQuery, 350); }); var applyQuery = function() { $scope.filter.query = $scope.query; };
/* */ <input ng-model="queryInput"/> <li ng-repeat= item in items | filter:filter.query>{{ item.title }} </li>
Source: https://habr.com/ru/post/200670/