Выделение длинного массива делает медленную прокрутку страницы в Angular.js

При попытке отобразить более 120 элементов из массива (с изображениями) прокрутка списка становится медленнее. В основном, когда я загружаю новые данные в бесконечный прокрутки, я объединяю старые данные массива с новыми данными массива.

С другой стороны, популярные сайты, такие как dribbble, behont, похоже, не имеют этой проблемы. Может быть, эта проблема специфична для Angular.js? Кто-нибудь сталкивался с этой проблемой в своих проектах?

Ответ 1

БЕСКОНЕЧНАЯ ПРОКРУТКА В ANGULARJS

Нет необходимости в дополнительных плагинах.

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>

Ответ 2

ngInfiniteScroll - это просто директива, которую вы можете использовать для реализации бесконечной прокрутки и не влияет на эту проблему.

вот несколько советов по ускорению приложения

  • Избегайте использования наблюдателей в повторяющейся секции, когда вы когда-либо можете

    • Используйте однократные привязки: {{::model}}
    • Уменьшить с помощью ng-*: все они добавляют $watch.
    • Уменьшить с помощью $watchCollection или $watch
    • Используйте ng-if вместо ng-show: он удаляет dom и уничтожает наблюдателей.
    • Используйте track by: для больших коллекций это значительно улучшает производительность рендеринга.
  • В конкатенировании:

    вы могли видеть вашу проблему в plunker и следующую команду

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

    лучше, чем

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

Но все вышеприведенные советы позволяют пользователю иметь больше элементов в списке, но когда количество элементов в списке получает больше (скажем 1000), прокрутка становится медленнее снова

Для этой проблемы мы могли бы использовать Angular Материал md-virtual-repeat, которые просто загружают видимые элементы по запросу, как я использовал в этом ваша проблема с виртуальным повтором.

Ответ 3

Думаю, вам стоит подумать об оптимизации вашего приложения, а не просто выбрать лучшую директиву или плагины. Слишком много областей также может замедлить работу приложения.