AngularJS Performance: How to update only those areas that, as I know, need to be updated?

I have an angular scope containing two things:

  • a giant table with 10k rows that takes a second to render
  • some small additional information on top of it in a fixed overlap header panel

Depending on how much you scroll the page / table, I need to update one of the small information bits in the header; you can think of it as a% counter, how far do you scroll.

To get the current scroll position, I wrote a directive (you can also find it here ):

app.directive "setWindowScroll", -> restrict: "E" scope: setVariable: "=" link: (scope) -> $(window).scroll -> scope.$apply -> scope.setVariable = $(window).scrollTop() 

My problem is that it does scroll in the u * nsuably slow * table. This is because the truthful with which I am writing with my directive is in additional information in the scope, and the change, which apparently causes angular to dirty check the entire change table when calling my $apply .

I know that this scroll will never change anything in my table and would like to limit my $apply affect the header of my site.

How can I make angular a non dirty table check?

+6
source share
2 answers

Angular does a dirty check in a process called a digest. When you make a call to $scope.$digest() , it will extend to all child areas of $scope . To notify angular of changes, you usually do $scope.$apply() . At the end of $ apply () angular, a digest is executed in the root area, which launches diggest in each area of ​​your application. Therefore, to avoid collecting data in your area with a large table area, you must make sure that it is not a child of the additional information and instead of doing $ scope. $ Apply () in your directive, you could make $ Volume. $ digest (). This can be a bit confusing, so I made a plunker that tries to show the difference. Open the console and see the difference in the scroll event and press the button:

http://plnkr.co/edit/45gKhAIt0DrozS7f0Bz2?p=preview

 // this will only cause a digest in the current scope and its children angular.element($window).bind('scroll',function(){ $scope.scrollY = $window.scrollY; $scope.$digest(); }) // this will cause a digest in every scope angular.element($window).bind('scroll',function(){ $scope.scrollY = $window.scrollY; $scope.$apply(); }) 

When all this is said, this is a very unusual thing - and probably not a good idea for a number of reasons (angular does not scale very well with thousands of elements, you cannot use any of the angular event directives (ngClick, etc.), because they are all wrapped in $ apply), but if you cannot display the table on the server side, you can try to try.

+3
source

I would like to know if this is possible, but - independently - you might consider not drawing the entire table at once.

Instead, limit it (and the number of related data / controllers in Angular -world) to only the lines that are displayed based on the current scroll position + some cached lines above and below. You can still store all the data in an array on the client, but only expose a small subset in Angular at any time.

One way to do this could be a small array in Angular -world, which you create with ng-repeat , and then add and remove elements in this small Angular array from a large non-w504> based on the scroll position.

Thus, Angular only knows about a small subset of your data and should do much faster. I think this should work well overall, because it also works much less for a browser that doesn't need to support the DOM tree and rendering for 10k lines.

0
source

Source: https://habr.com/ru/post/944109/


All Articles