【问题标题】:Improve performance of ng-repeat with 1600 items. Causing page load delay and performance issues使用 1600 个项目提高 ng-repeat 的性能。导致页面加载延迟和性能问题
【发布时间】:2018-03-09 00:24:21
【问题描述】:

我有一个带有完美滚动条的 UI 布局来呈现项目列表。我需要在可滚动部分中显示 1600 个项目(不限制以任何分页显示的项目数量),以便用户可以一次滚动所有项目(这是对我的要求,我对此控制较少) .

渲染此视图的角度模板如下:

<my-scrollable-section>
    <div 
        ng-class="myCtrl.itemId == item.itemId ? 'item-active-background' : ''"
        ng-click="myCtrl.itemClickHandler(item)"
        ng-repeat="item in myCtrl.items | filter:myCtrl.search track by item.itemId">
            <span>{{item.name}}</span>
            <div ng-repeat="(key, value) in ::item.models">
                <span>{{::value}}</span>
            </div>
            <div ng-repeat="(key, value) in ::item.frameworks">
                <span>{{::value}}</span>
            </div>
    </div>
</my-scrollable-section>

此重复中的过滤器链接到此视图正上方的搜索栏,以缩小显示的项目范围。

现在的问题是:

  1. 页面不会立即加载并冻结 5-8 秒。观察者的数量不是造成这种情况的原因,因为我尝试了一次性绑定以使观察者数量低于 1500。
  2. 页面加载后,滚动速度非常慢,看起来一点也不友好。
  3. 我尝试建议分页来限制一次呈现的项目数量,但如前所述,我几乎无法控制要求,并且要求所有项目都出现在可滚动列表中。

这些负载和性能问题可以用 Angular 解决吗?请不要建议无限滚动,因为即使我们使用无限滚动,最后,一旦所有项目都在页面上,UI会再次变慢。

【问题讨论】:

  • 所以你需要虚拟卷轴。采取任何你喜欢的实现。
  • 如果我选择虚拟滚动,它会干扰我已经用于滚动的完美滚动。另外,这是否会以某种方式限制项目以使页面加载更快一些?
  • 如果需要,您可以使用 limitTo 并在 ng-repeat 中添加搜索功能。
  • 第 3 点“我尝试建议分页以限制一次呈现的项目数量,但如前所述,我几乎无法控制要求,并且要求所有项目都存在可滚动列表。”。
  • 尝试延迟加载滚动?假设可以在视口中放置 10 个项目,然后最初加载 20 个项目。滚动开始加载接下来的 20 个项目。

标签: angularjs angularjs-directive


【解决方案1】:

// 尝试使用,滚动调用函数并更新 renderLimit 值。

在此处查看示例 - plunker demo

// set initial limit to say 30.
$scope.renderLimit = 30;
// bind this function with directive.
$scope.updateLimit = function(value){
  if(value == 'bottom'){
    $scope.contValue += 1;
    $scope.renderLimit += 30;
  }
};

// directive will be
// custome directive for scrollHandler
app.directive('scrollHandler', function(){
  return{
      scope: { 
             scrollHandler: '&',
             dataChange:'='
         },
      link:function(scope,element){

          scope.$watch(function(){return scope.dataChange;},function(){
              if(element[0].scrollTop > (element[0].scrollHeight - element[0].clientHeight - 50))
                element[0].scrollTop=(element[0].scrollHeight - element[0].clientHeight - 50);
          });
          element.bind('scroll',function(){
              var scrPosition = element[0].scrollTop;

              if(scrPosition === 0)
                 scrPosition = "top";
              else if(scrPosition === (element[0].scrollHeight - element[0].clientHeight))
                 scrPosition = "bottom";
              scope.$apply(function() {
                 scope.scrollHandler()(scrPosition);
               });
          });

      },
      restrict:"A"
  };
});

HTML::

<div scroll-handler="myCtrl.updateLimit" data-change="contValue">
    <div 
            ng-class="myCtrl.itemId == item.itemId ? 'item-active-background' : ''"
            ng-click="myCtrl.itemClickHandler(item)"
            ng-repeat="item in myCtrl.items| limitTo:renderLimit | filter:myCtrl.search track by item.itemId">
      // item contents...
    </div>
</div>

【讨论】:

  • 有没有关于如何使用onScrollHandler函数的参考或例子?
  • 为此,完美的滚动条事件需要以角度处理。任何指针如何做到这一点?
  • onScrollHandler 可以通过多种方式进行处理,其中一种我使用了指令。请查看 plunker 演示。
  • 这种方法的几个问题: 1. 而不是 $scope.initialLimit += 30; , 它应该是 $scope.renderLimit += 30;因为 initialLimit 没有在模板中的任何地方使用。 2. 连续滚动到最后,我又回到了同样的问题(ng-repeat 中的项目列表很大,这使得 DOM 变慢)。对此方法的任何更新都将受到高度赞赏,因为这种方法非常接近我想要实现的目标。只是我们需要不断减少列表顶部的项目以及滚动到底部以保持渲染列表较小。
【解决方案2】:

你看过vs-repeat吗?

我一直在使用这个 api 来处理大量要重复的项目。而且我没有遇到任何问题。

只是一个简单的:

<div vs-repeat> <div ng-repeat="item in someArray"> <!-- content --> </div> </div>

会解决你的问题。

【讨论】:

  • 我可以在完美滚动条部分使用 vs-repeat 吗?
  • 我尝试了 vs-scroll 但它在完美滚动条部分内不起作用。在这种情况下,您有可以提供帮助的工作示例或小提琴吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 1970-01-01
  • 2012-03-29
  • 2016-01-01
  • 1970-01-01
相关资源
最近更新 更多