Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Long array list rendering makes page scrolling slow in Angular.js

When trying to render more than 120 items from an array (with images) the scrolling of the list becomes slower. Basically, when I am loading new data in infinite scroll, I am concatenating old array data with new array data.

On the other hand, popular websites like dribbble, behance dont seem to have this issue. Maybe this issue is specific to Angular.js? Has anyone faced this problem in their projects?

like image 809
shrbisht Avatar asked Feb 08 '17 05:02

shrbisht


2 Answers

INFINITE SCROLLING IN ANGULARJS

No need of any additional plugins.

app = angular.module("demo", []);

app.controller("MainController", function($scope, $http){
  
  // the array which represents the list
  $scope.items = ["1. Scroll the list to load more"];
  $scope.loading = true;
  
  // this function fetches a random text and adds it to array
  $scope.more = function(){
    $http({
      method: "GET",
      url: "https://baconipsum.com/api/?type=all-meat&paras=2&start-with-lorem=1"
    }).success(function(data, status, header, config){
      
      // returned data contains an array of 2 sentences
      for(line in data){
        newItem = ($scope.items.length+1)+". "+data[line];
        $scope.items.push(newItem);
      }
      $scope.loading = false;
    });
  };
  
  // we call the function twice to populate the list
  $scope.more();
});

// we create a simple directive to modify behavior of <ul>
app.directive("whenScrolled", function(){
  return{
    
    restrict: 'A',
    link: function(scope, elem, attrs){
    
      // we get a list of elements of size 1 and need the first element
      raw = elem[0];
    
      // we load more elements when scrolled past a limit
      elem.bind("scroll", function(){
        if(raw.scrollTop+raw.offsetHeight+5 >= raw.scrollHeight){
          scope.loading = true;
          
        // we can give any function which loads more elements into the list
          scope.$apply(attrs.whenScrolled);
        }
      });
    }
  }
});
li{
  display:block;
  list-style-type:none;
  margin-bottom: 1em;
}

ul{
  height:250px;
  background: #44E394;
  color: #fff;
  overflow:auto;
  width:550px;
  border-radius: 5px;
  margin:0 auto;
  padding: 0.5em;
  border: 1px dashed #11BD6D;
  &::-webkit-scrollbar{
    width:8px;
    background-color:transparent;
  };
  &::-webkit-scrollbar-thumb{
    background-color:#b0fccd;
    border-radius:10px;
  }
  &::-moz-scrollbar{
    width:8px;
    background-color:transparent;
  };
  &::-moz-scrollbar-thumb{
    background-color:#b0fccd;
    border-radius:10px;
  }
  &::-ms-scrollbar{
    width:8px;
    background-color:transparent;
  };
  &::-ms-scrollbar-thumb{
    background-color:#b0fccd;
    border-radius:10px;
  }
}

body{
  text-align:center;
  font-size:1.2em;
  font-family: "Helvetica";
  color: #44E394;
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAG0lEQVQIW2P88OHDfwY0wAgSFBAQYEQWp1AQAKUbE9XRpv7GAAAAAElFTkSuQmCC) repeat;
  padding: 2em;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div data-ng-app='demo'>
  <div data-ng-controller='MainController'>
    <ul class='hello' when-scrolled='more()'>
      <li data-ng-repeat='item in items'>
        {{item}}
      </li>
    </ul>
    <div data-ng-show='loading'>Loading</div>
  </div>
</div>
<h1>INFINITE SCROLLING IN ANGULARJS</h1>
like image 74
Alagendran Ayyadurai Avatar answered Oct 23 '22 10:10

Alagendran Ayyadurai


ngInfiniteScroll is just a directive that you can use to implement infinite scrolling and it doesn't affect this problem.

here are some tips to speed up the app

  • Avoid using watchers in repeating section when ever you can

    • Use one time bindings : {{::model}}
    • Decrease using ng-* : all of them add a $watch.
    • Decrease using $watchCollection or $watch
    • Use ng-if instead of ng-show : it removes dom and destroys watchers in.
    • Use track by: For large collections, this significantly improves rendering performance.
  • In Concatenating:

    you could see your problem in plunker and next command

        [].push.apply($scope.list,getNewList());
    

    is better than

        $scope.list=$scope.list.concat(getNewList());
    

But all above tips lets user have more items in the list but when number of items in the list get more than (let say 1000) the scrolling becomes slow again

For this problem we could use Angular Material md-virtual-repeat which just load visible items on demand as i used in this your problem with virtual repeat.

like image 6
fingerpich Avatar answered Oct 23 '22 10:10

fingerpich