最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Long array list rendering makes page scrolling slow in Angular.js - Stack Overflow

programmeradmin1浏览0评论

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?

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?

Share Improve this question asked Feb 8, 2017 at 5:36 shrbishtshrbisht 6763 gold badges9 silver badges25 bronze badges 15
  • The main point to understand here is you are loading data from server or local ? and if its in local you can use limitTo filter rather than concatination – Vinod Louis Commented Feb 8, 2017 at 5:38
  • Perhaps have a look at a directive like ngInfiniteScroll to progressively load the items you need rather than all at once – haxxxton Commented Feb 8, 2017 at 5:39
  • 3 Happened with me when I had a bulky array rendered using ng-repeat but without track by. See if you are missing that – tanmay Commented Feb 8, 2017 at 5:53
  • 1 If you're looking at tips to improve performance, here's a post i've made earlier which talks about some of the things you could try: stackoverflow.com/a/38349146/841804 – Chanthu Commented Feb 8, 2017 at 6:01
  • ng-repeat is great but when Array has more than 20-30 elements it become painfully slow. I read somewhere that is because of re-render all items in every update. You could try use one time bindings but it helps only a little. When we bulid Chat App instead of angular ng-repeat We have to use pure JS to list messages. – Dominik Ruczyński Commented Feb 22, 2017 at 15:31
 |  Show 10 more comments

3 Answers 3

Reset to default 10 +50

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>

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.

I think you should think about optimize your application, not just select a better directive or plugins, Too many scopes can also slow the application.

发布评论

评论列表(0)

  1. 暂无评论