AngularJS中从顶部无限滚动(反向)

14
我正在尝试进行反向无限滚动。我有一个评论列表,其中我接收到最近的10条评论,并希望用户能够向上滚动以检索下一个10条-类似于FB,它显示最新的评论与“获取前一个”链接,而不是链接通过滚动事件。

我从http://jsfiddle.net/vojtajina/U7Bz9/开始,并尝试将其修改为反向无限滚动,很快就得到了这样的结果:

  function Main($scope, $timeout) {
    $scope.items = [];

    var counter = 0;
    $scope.loadMore = function() {
      // simulate an ajax request
      $timeout( function() {
        for (var i = 0; i < 5; i++) {
          $scope.items.unshift({id: counter});
          counter += 10;
        }}, 1000);
    };

    $scope.loadMore();
  }

  angular.module('scroll', []).directive('whenScrolled', ['$timeout', function($timeout) {
    return function(scope, elm, attr) {
      var raw = elm[0];

      $timeout(function() {
        raw.scrollTop = raw.scrollHeight;
      }, 1100);

      elm.bind('scroll', function() {
        // note: if test for < 100 get into infinite loop due to 
        // the delayed render
        if (raw.scrollTop === 0) {
          var sh = raw.scrollHeight
          scope.$apply(attr.whenScrolled);
          // the items are not loaded and rendered yet, so
          // this math doesn't work
          raw.scrollTop = raw.scrollHeight - sh;
        }
      });
    };
  }]);
  ​

http://jsfiddle.net/digger69/FwWqb/2/

问题在于,当获取下一批10个项目时,它们被添加到列表顶部并且整个列表重新渲染,处于列表末尾的项目完全滚出视图。在示例中,项目“40”位于顶部,当您向下滚动并向上滚动以触发滚动时,“90”项目将位于顶部。我正在寻找一种良好的策略,在呈现后将“40”保持在滚动区域的顶部。
注意:在示例中,我通过在滚动事件中保存顶部li并调用scrollIntoView()直到我添加模拟ajax调用的超时,使其正常工作。有了超时,请求回来之前顶部li就会滚动到视图中,并且新元素被呈现出来 :/
var top = elm.find("li")[0];
scope.$apply(attr.whenScrolled);
top.scrollIntoView();
2个回答

22
你可以尝试像这样做:http://jsfiddle.net/mNFmf/4/。这将滚动到div的底部:
$timeout(function() {
    raw.scrollTop = raw.scrollHeight;          
});    

这样可以防止 div 滚动到列表中的第一项:

And this will keep the div from scrolling up to the first item on the list:
var sh = raw.scrollHeight
scope.$apply(attr.whenScrolled);
raw.scrollTop = raw.scrollHeight - sh;

更新

为了解决ajax请求问题,请尝试使用promises

http://jsfiddle.net/mNFmf/8/

加载器应该类似于这样:

$scope.loadMore = function() {
  var deferred = $q.defer();

  // do ajax request here and after getting the result call:   
  deferred.resolve();

  return deferred.promise;
};

另一方面:

loadMore.then(function() { 
  /* do whatever you want after the ajax request has been fulfilled */ 
});

谢谢回复。好主意……然而我遇到的问题是,scope.$apply(attr.whenScrolled) 是一个 ajax 调用,因此当运行 raw.scrollTop = raw.scrollHeight - sh 时,新项目尚未呈现。我将更新问题和 fiddle 来演示。 - Mark Nadig
这个救了我!! - justcode

0
你解决过这个问题吗?我们正在使用一些技巧来读取和设置 scrollTop,但发现当我们滚动到一个位置并查询新位置时,Safari在设置和读取scrollTop方面存在一些奇怪的时间问题,因为它仍然保留旧位置。

它对我们一直有效 - 但我们的目标平台是移动设备。注意:我在周末看到了这个 - https://github.com/BinaryMuse/ngInfiniteScroll - Mark Nadig
@digger69 我作为作者很感兴趣知道这对你在这个特定目的上是否有用。 - Michelle Tilley
7
你好,@BrandonTilley。能否将ngInfiniteScroll用于反向无限滚动?谢谢! - Amal Antony

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接