AngularJS延迟渲染(不是延迟加载视图)

时间:2015-10-18 19:41:09

标签: javascript angularjs

让我说我有很多(3000+)项目我要在一个高度固定且ng-repeat的div中呈现(在overflow: auto中),所以我&#39 ; d获取N个可见项目和其余部分的滚动条。

我猜这么多项目的简单ng-repeat可能需要花费很多时间。有没有办法让AngularJS只渲染那些可见的N项?

编辑:

无限卷轴不是我想要的。我希望用户能够滚动到列表的任何一点,所以我真的想要一个类似文本编辑器的行为。换句话说:我喜欢滚动条包含" height"所有项目,但在DOM中只有几个。

2 个答案:

答案 0 :(得分:1)

  

此答案提供了一种方法,用于延迟呈现当前在视图中的项目,如原始问题的编辑所定义。 我希望用户能够滚动到列表的任何一点,所以我真的想要一个类似文本编辑器的行为。换句话说:我喜欢滚动条包含" height"所有项目,但只在几个DOM中。

在尝试此操作之前安装angular-inview插件。

为了获得您的滚动高度,您需要为数组项目保留空间。所以我从一个包含3000个简单项目的数组开始(或者在你想要的任何程度上与无限滚动相结合。)

var $app = angular.module('app', ['infinite-scroll']);

$app.controller('listingController', function($scope, $window) {
  $scope.listOfItems = new Array($window._bootstrappedData.length);
  $scope.loadItem = function($index,$inview) {
    if($inview) {
      $scope.listOfItems[$index] = $window._bootstrappedData[$index];
    }
  }
});

由于我们正在讨论灵活的高度,因此我会为您的内容预渲染创建一个占位符。

<div ng-controller="listingController">
  <ul>
    <li ng-repeat="item in listOfItems track by $index" in-view="loadItem($index,$inview)" style="min-height:100px"><div ng-if="item">{{item.name}}</div></li>
  </ul>
</div>

使用ng-if将阻止渲染逻辑不必要地运行。将项目滚动到视图中时,它会自动显示。如果您想等待一秒钟以查看用户是否仍在滚动,您可以在loadItem方法中设置超时,如果在合理的时间段内将相同的索引推出视图,则会取消。

  

注意:如果您真的想避免在DOM中添加任何内容,可以将可滚动区域设置为&#34;占位符&#34;的特定倍数。高度。然后,您可以创建一个使用该高度的指令来确定应显示的项的索引。一旦显示新项目,您就需要将它们的高度添加到总数中,并确保将它们放在正确的位置,并确保您的指令知道如何将这些高度解释为评估下一组显示的元素。但我觉得这太过激进和不必要了。

答案 1 :(得分:0)

  

扩展Grundy使用.slice()

的观点

当我需要延迟渲染/延迟加载数据时,我使用ngInfiniteScroll

我会保留范围内的3000条记录 ,以防止不必要地减轻您的摘要性能,然后根据需要将它们附加到范围数据中。这是一个例子。

var $app = angular.module('app', ['infinite-scroll']);

$app.controller('listingController', function($scope, $window) {

  /*
   * Outside of this controller you should bootstrap your data to a non-digested array.
   * If you're loading the data via Ajax, save your data similarly.
   * For example:
   * <script>
   *   window._bootstrappedData = [{id:1,name:'foo'},{id:2,name:'bar'},...];
   * </script>
   */
  var currentPage, pageLength;
  $scope.listOfItems = [];
  currentPage = 0;
  pageLength = 100;
  $scope.nextPage = function() {
    // make sure we don't keep trying to slice data that doesn't exist.
    if (currentPage * pageLength >= $window._bootstrappedData.length) {
      return false;
    }

    // append the next data set to your array
    $scope.listOfItems.push($window._bootstrappedData.slice(currentPage * pageLength, (currentPage + 1) * pageLength));
    currentPage++;
  };

  /*
   * Kickstart this data with our first page.
   */
  return $scope.nextPage();
});

你的模板:

<div ng-controller="listingController" infinite-scroll="nextPage()" infinite-scroll-distance="3">
  <ul>
    <li ng-repeat="item in listOfItems">{{item.name}}</li>
  </ul>
</div>