防止AngularJS在每个$digest周期中检查数千行数据的脏检查问题

3
我有一个数据源,可能有几千行。我希望用户能够滚动列表并过滤它,而不会出现性能问题。每当记录更改时,我的数据源会自动触发一个事件。
目前,这些数据映射到$rootScope.datasource。
我想能够将这个大数据集与Angular的$digest循环隔离开,并防止Angular在应用程序其他地方发生无关事件时每次脏检查数千行。我只希望在告诉它之后(在我的某个更改事件触发后),Angular才$digest数据源。
我已经看过像BindonceWatch Fighters这样的库。如果数据是完全静态的,则这是一个很好的选择,但我的记录偶尔会更改,我希望UI在我告诉它更新时更新。
Angular目前是否支持这种功能?

请使用 https://github.com/Pasvaz/bindonce 进行尝试。 - Stewie
Bindonce能让我在数据修改后更新DOM吗?据我所知,这仅适用于静态数据。 - Colin Skow
为什么要映射到$rootScope属性?在服务中隔离数据。很少需要将数据放在$rootScope级别。 - charlietfl
因为大多数控制器共享相同的数据。我有一个服务,每当记录更改时触发事件,并将实时数据保存在$rootScope中,以便可以绑定到DOM。 - Colin Skow
2个回答

2

不应该观察大型数据集。相反,观察描述数据集状态的单个值。这个单个值可以是增量计数器或你数据的哈希值。如果这个值发生变化,观察监听函数将被调用。

另一种选择是在第一次使用后取消观察器,并在数据集更改后重新注册它。

此外,你应该尽量不使用观察器,而是使用更新后的状态进行广播$broadcast


这是很好的想法。我如何在ng-repeat中使其工作?有没有一种使用Bindonce来实现这个的方法? - Colin Skow
1
@ColinSkow 没有办法优化ng-repeat的内部watcher。它使用$watchCollection,因此始终检查集合中的所有项。您可以使用另一个预过滤数据集作为ng-repeat的源对象来加速检查。该对象应填充有过滤数据,并仅在上游数据集更改时进行更新。此外,您可以通过新的ng-repeat语法尽量减少DOM更新:variable in expression track by tracking_expression - yaroslav
这是我要走的方向。我还没有在我将使用的数据类型上测试性能,但可能最终会创建自己的hg-repeat版本。 - Colin Skow
quick-ng-repeat 可以通过仅监视单个值来加速您的列表和表格,就像所描述的那样。此外,我还必须提到 scalyr,因为它对我们非常有帮助。 - user1563700

1
你可以使用 bindonce,当你知道已经有更改时强制更新UI。要触发此更新,您需要重新编译模板。我在这个 plunker 中通过“滥用”ng-include 来实现这一点,但你也可以编写一个特殊的指令来完成这个操作。

这是一个好主意,但在大型数据集上可能不太实用,因为它会导致闪烁。 - Colin Skow

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