【问题标题】:AngularJS Infinite Scrolling with lots of dataAngularJS无限滚动有大量数据
【发布时间】:2013-01-11 15:08:59
【问题描述】:

所以我正在尝试使用 AngularJS 创建一个无限滚动表,类似于:http://jsfiddle.net/vojtajina/U7Bz9/

我遇到的问题是,在 jsfiddle 示例中,如果我一直滚动直到获得一百万个结果,浏览器就会慢到爬行,不是吗?因为现在在 $scope.items 中会有 1,000,000 结果。例如,如果我在 $scope.items 中一次只有 1000 结果,而我正在查看的结果恰好在这些 1000 中,那就更好了。

示例用例:页面加载,我看到了第一个10 结果(来自1,000,000)。尽管我只看到10,但实际上已经加载了第一个1000 结果。然后我滚动到列表的最底部以查看最后的10 项目。如果我再次向上滚动到顶部,我希望顶部的10 结果将不得不从服务器再次加载。

我有一个使用 ExtJS 完成的项目,情况类似:一个包含数千个结果的无限滚动列表。 ExtJS 处理这个问题的方法是加载当前页面的结果,然后预加载几个额外的结果页面。然而,在任何时候,只有10 页的结果存储在本地。

所以我想我的问题是如何在 AngularJS 中实现它?我知道我没有提供太多代码,所以我不希望人们只给出编码的答案,但至少给出一些方向的建议。

【问题讨论】:

  • 为什么 Angular 实现与 ExtJS 实现有那么大的不同?换句话说,ExtJS 实现的哪一部分在移植到 Angular 时遇到了困难?看起来你仍然会预加载,只是调整 $scope.items 中的内容,而不是调整 DOM 中的内容(我猜 ExtJS 实现就是这样做的)。而不是 DOM 操作,只需进行 $scope 操作并让 Angular 自动更新视图。
  • @MarkRajcok 既然您已经说过这似乎很明显:P 但是有一件事我仍然不确定该怎么做。在 ExtJS 中,无限滚动列表的滚动条给人的印象是所有数据都已加载,即我可以将滚动条移动到底部,然后我会看到最后一项。你会如何在 AngularJS 中模仿这一点?
  • 这会很困难,因为 Angular 控制着视图的显示,而当前滚动条的大小无疑与 $scope.items 的当前大小有关。您可能需要编写自己的指令来实现自定义可滚动容器(如果您真的认为需要此功能)。
  • 无限滚动最近普遍受到审查,因为有很多问题:可用性、搜索引擎优化、流量,以及当您到达“1,000,000”行时与 DOM 相关的性能问题。也许是时候重新考虑实施了。
  • 我觉得react.js可以用在这样的场景中

标签: javascript angularjs


【解决方案1】:

有几点:

  1. 无论框架如何,“无限滚动”到“1,000,000”行都可能会出现问题,因为您已经创建了数百万个 DOM 节点(假设每条记录中有多个元素)

  2. 您正在考虑使用 <li ng-repeat="item in items">{{item.foo}}</li> 或类似的实现会很快出现问题非常,原因有一个:{{item.foo}}} 或任何类似的 ngBind 都会设置$watch 在该字段上,这会以函数引用等形式产生大量开销。因此,虽然“数组”中的 10,000 个小对象不会那么糟糕...... 10,000-20,000 个额外的函数引用对于这 10,000 项中的每一项。

在这种情况下,您想要做的是创建一个指令来处理添加和删除“太远”的 DOM 元素以及保持数据最新。这应该可以缓解您可能遇到的大多数性能问题。

...好的无限滚动并不简单,我很抱歉。

【讨论】:

  • 我完全同意你所说的。我想要做的只是实际加载“可见”的几行数据。我遇到的问题是如何给人以这些行是更大数据集的一部分的印象。
  • 我在这里寻找 dom unloader
【解决方案2】:

我喜欢angular-ui实现ui-scroll...

https://github.com/angular-ui/ui-scroll

... 在 ngInfiniteScroll 上。 ui-scroll 与标准无限滚动的主要区别在于,在离开视口时会删除先前的元素。

从他们的自述文件...

向用户呈现未定义长度的数据元素列表的常用方法是从列表顶部的一小部分开始 - 刚好足以填满页面上的空间。当用户向下滚动列表时,额外的行会附加到列表的底部。

这种方法的问题在于,即使列表顶部的行在滚动出视图时变得不可见,它们仍然是页面的一部分并且仍然消耗资源。随着用户向下滚动,列表会增加,网络应用会变慢。

如果代表一行的 html 附加了事件处理程序和/或角度观察程序,这将成为一个真正的问题。一个平均复杂度的 Web 应用程序可以轻松地每行引入 20 个观察者。对于 100 行的列表,您总共有 2000 个观察者和一个缓慢的应用程序。

此外,ui-scroll 被积极维护。

【讨论】:

  • 投你一票,虽然我讨厌从已经工作但维护不善的无限滚动切换
【解决方案3】:

看来http://kamilkp.github.io/angular-vs-repeat 就是您要找的东西。它是一个虚拟滚动指令。

【讨论】:

  • 这个真的很棒,但我在阅读了他们已知的限制后我并不幸运。 +1
【解决方案4】:

事实证明,AngularJS 的 ng-grid 模块几乎完全符合我的需要。如果你看examples page,Server-Side Processing Example 也是一个无限滚动列表,只加载需要的数据。

感谢那些评论和回答的人。

最新网址:ng-grid

【讨论】:

  • 示例页面似乎与您的原始问题不匹配。它们只渲染视口内的 DOM 元素,但不加载数据以匹配视口。他们正在使用传统的分页加载数据。也许他们改变了他们的榜样。它是否按照您最初问题中的描述工作?
  • @RichardZschech 不,后来我发现这些示例按照您的描述工作。我没有寻找替代方案,因此我改变了页面的设计。
  • 这看起来是最强大的模块化解决方案。扩展行的能力绝对是一个不错的加分项。我没有看到任何其他库的那么多功能。 ng-vs-scroll 看起来性能很高,但也好像在 git 树上烂掉了 =/.
【解决方案5】:

您可以尝试使用 ng-infinite-scroll :

http://binarymuse.github.io/ngInfiniteScroll/

【讨论】:

  • 请注意,这是针对 Facebook 风格的真正无限滚动,滚动条开始调整为初始加载内容的大小,然后随着用户滚动到目前已加载内容的末尾而反复跳转。这与将一个有限但长的列表替换为一个大小为表的高度的大盒子(如果所有行都已加载),并使用固定高度的行在用户滚动时动态加载到行集中,因此滚动条永远不会跳跃(正如这个问题最初提出的那样)。很遗憾,对于这种区别没有明确的术语。
【解决方案6】:

从 Angular Material 查看virtualRepeat

它实现了对视口区域中可见行的动态重用,就像 ui-scroll 一样

【讨论】:

  • 它可能适用于非常基本的情况。但是,如果您实际上有更多指令作为列表项,则此组件有一些限制。 see discussion
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
相关资源
最近更新 更多