【问题标题】:Filtering a page with infinite scroll in AngularJS在AngularJS中过滤无限滚动的页面
【发布时间】:2012-10-18 15:15:58
【问题描述】:

我在 AngularJS + Node.js 应用程序上实现了无限滚动功能。

它基于这个 JSfiddle 并且工作方式相同:http://jsfiddle.net/vojtajina/U7Bz9/ HTML:

<div id="fixed" when-scrolled="loadMore()">
  <ul>
   <li ng-repeat="i in items">{{i.id}}</li>
  </ul>  
</div>​

Javascript:

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

  var counter = 0;
   $scope.loadMore = function() {
     for (var i = 0; i < 5; i++) {
        $scope.items.push({id: counter});
        counter += 10;
     }
   };

  $scope.loadMore();
}

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

    elm.bind('scroll', function() {
        if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
            scope.$apply(attr.whenScrolled);
        }
    });
  };
});

我实现无限滚动的原因是为了节省我的用户带宽,除非用户想查看所有结果,否则不加载所有 1000 个结果及其相应的图像。

但是,当使用 AngularJS 过滤器在结果中搜索时,我遇到了问题,因为当然不是所有的结果都在那里(除非用户滚动到最底部),所以搜索只会返回所需结果的一小部分.

然后我删除了无限滚动功能以使搜索功能正常工作,但这在我打开页面时在 chrome 上(不是在 Firefox 上)提供了新问题,浏览器开始从顶部加载图像。如果我然后通过搜索以“z”开头的内容(在结果的最底部)来过滤结果,Firefox 会切换焦点并首先加载以“z”开头的结果(因为它们是唯一显示的结果)。然而,chrome 会继续通过列表加载,因此用户只有在加载应用中的所有图像后才能看到他们的搜索结果(对于“z”)。

我正在寻找一种方法,让 angular 同时提供无限滚动和适当的搜索过滤器结果。如果这是不可能的,那么一种方法可以让 chrome 首先加载可见图像。

我目前正在尝试一些奇怪的东西,范围内有一堆不同的数组,但到目前为止我还没有运气。

【问题讨论】:

  • 另一个用例示例在 AngularJS 教程中。如果this page: 有 100 万条结果,图像是高分辨率的,并且用户搜索 ZZZOOM Phone 5000,那么我将如何确保 chrome 在加载其他手机的所有图像之前加载 ZZZOOM PHone 5000 的图像。 (IE、Firefox 和 Safari 已经自动完成的方式。)

标签: node.js google-chrome angularjs express


【解决方案1】:

由于这里有几个人遇到了类似的问题,而我自己也在苦苦挣扎,所以我花时间创建了一个可行的小提琴(针对我的情况)。

https://jsfiddle.net/lisapfisterer/Lu4sbxps/

主要思想是使用无限滚动的函数调用动态扩展limitTo值

<div infinite-scroll="loadMore()" infinite-scroll-distance="20">
    <tr data-ng-repeat="logEvent in logEventFilter = (logEvents | filter:searchTerm | limitTo:numberToDisplay) track by $index">
        <td> {{$index}} </td>
        <td> {{logEvent.name}} </td>
        <td> {{numberToDisplay}} </td>
    </tr>
</div>

loadMore 只是增加了限制

$scope.loadMore = function() {
    if ($scope.numberToDisplay + 5 < $scope.logEvents.length) {
        $scope.numberToDisplay += 5;
    } else {
        $scope.numberToDisplay = $scope.logEvents.length;
    }
};

【讨论】:

  • 这确实对我有用,但部分是因为我仅在触发“deviceReady”时才加载“logEvents”,所以我以前不能这样做。我的问题是执行代码时 $scope.logEvents 未定义。我尝试将“loadMore”范围函数放在“deviceReady”中,但不起作用。有任何想法吗?谢谢。
  • 现在我已经测试了一段时间知道 loadMore() 不应该在那个时候触发,它只能在滚动时触发,这就是我的问题,也许我标记为无限-scroll="loadMore()" 错误的 html 标签。
  • 检查你是否使用了最新版本的infinite-scroll.js v1.2.2 (cdnjs.cloudflare.com/ajax/libs/ngInfiniteScroll/1.2.2/…)。该网站仅链接 v1.0.0,但新版本修复了一些问题。还将“if ($scope.logEvents) { ... } 添加到您的函数中,以便仅在列表已填满时执行。
  • 其实我发现cdnjs里的那个也过时了,我从github上拿了一个(raw.githubusercontent.com/sroze/ngInfiniteScroll/master/build/…)来测试一下。关于在设备准备好时声明 loadMore() 的需要,我修复了它,将 ng-if="!isLoading" 添加到具有infinite-scroll="loadMore()" 的标签中,这使得我得到数据后加载html ...但我真的一直认为 loadMore() 在呈现列表的 DOM 之前触发,因为它在开始时触发,并且只有 ONCE :/
【解决方案2】:

你想做的不是“不可能”,但肯定会有点复杂。

  • 让您的服务器执行所有“过滤”以确保返回的分页值是过滤器的正确值。
  • 当服务器返回结果时,将所有的 HTML 渲染到屏幕上除了图像标签的 src 属性。这样一来,任何图像都不会开始加载。
  • 滚动到正确的“页面”。
  • 确保加载图像之前的所有高度都相同,现在执行一些 JS 魔术来确定哪些是可见的。
  • 仅设置可见图像的 src 属性,订阅其“加载”事件并创建一个 $q 承诺,一旦所有加载完成,该承诺即完成。
  • 该承诺完成后,设置其余图像 src 属性,以便加载其余图像。

【讨论】:

  • 感谢您的帖子。最后解决方案非常简单,我所要做的就是改变无限滚动的工作方式。我没有在范围内推送到缩短的数组,而是在过滤器中执行此操作。过滤器将完整数组作为其参数,如下所示 - searchFilter:text:count 过滤器根据计数限制返回数组的长度,并且每次滚动到页面底部时计数都会增加。我将在今天晚些时候发布一个有效的 JSFiddle,以便其他人可以看到它。
  • 撞……那个小提琴@RickKleinhans在哪里?嗯 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-26
  • 2021-07-05
  • 1970-01-01
  • 2012-10-11
  • 1970-01-01
  • 2023-03-08
  • 2021-02-09
相关资源
最近更新 更多