我有一个带有分页网格的AngularJS应用程序(两个嵌套的ng-repeat)。一个页面大约有25x40个输入元素。在最初进行了1000次绑定时,分页性能是可以接受的。
但随之而来的是页面的复杂性增长:动态类,变化的上下文菜单,网格中每个单元格的条件内容。估计有6000个绑定(每个输入元素6个),分页变得无法使用。
我的问题是:我如何解决AngularJS中的性能问题?显而易见的第一步是衡量。但是Chrome Profiler的结果并没有告诉我那么多,远远不知道如何继续。
Self Total Function
-----------------------------------------------------------------
24 ms 2.79 s angular.js:7997 Scope.$digest
1 ms 1 ms controllers.js:365 setViewportData
16 ms 692 ms angular.js:13968 ngRepeatWatch
8 ms 22 ms angular.js:6439 extend.literal
9 ms 1.22 s angular.js:14268 ngSwitchWatchAction
16 ms 45 ms angular.js:12436 ngModelWatch
0 621 ms angular-ui-4.0.js:264 initDateWidget
0 13 ms angular.js:12859 ngClassWatchAction
0 70 ms angular.js:14184 ngStyleWatchAction
1 ms 5 ms angular-ui-4.0.js:261 getOptions
0 16 ms angular.js:579 copy
0 1 ms angular.js:4558 interpolateFnWatchAction
1 ms 2 ms angular.js:5981 token.fn.extend.assign
0 37 ms angular.js:8151 Scope.$eval
1 ms 1 ms angular.js:6137 extend.constant
14 ms 16 ms angular.js:651 equals
1 ms 1 ms angular.js:4939 $interpolate.fn旁白:“initDateWidget()”有没有可能在未来加快速度(忽略'Object.observe()‘,这显然是另一个话题)?
发布于 2013-03-27 01:39:18
你可以做的事情是最大限度地提高你的Angular应用的速度,那就是尽可能地减少这些绑定。要做到这一点,一种方法是创建一个指令,该指令使用DOM操作而不是使用ng-repeats为您构建表。这将减少您必须处理的总监视数量,并使$digest更快。
我知道这样做很丑陋,但是Angular实际上并不是用来设置3000+绑定的。因为它做了摘要,而不是观察者模式,所以在设置了那么多的情况下,它真的会减慢速度。
您甚至可以采用一种混合方法,其中仍然使用ng-repeat,但是所有的值都放在DOM中,使用来自自定义指令的直接DOM操作,从而避免了所有绑定。
发布于 2013-03-30 05:35:12
如果你还没有这样做,请安装AngularJS浏览器插件Batarang,它将帮助你精确定位哪些绑定导致了你的悲痛。https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en
正如另一个答案所暗示的,您正在寻找的可能是表格的无限滚动设置的一个小例子,其中您绑定到的模型是您在屏幕上显示的子集。
ng-grid组件实现了这一点,可能值得一看,要么直接使用它,要么窃取这项技术。http://angular-ui.github.com/ng-grid/
发布于 2014-02-12 19:34:04
资源
This post about angularJS performance on large lists很好地概述了用于性能调优的选项。
上面的答案(除了Batarang插件)也在里面提到了。这只是那篇文章中技巧的概述。
使用limitTo减少数据(分页)
更明显的解决方案之一是通过减少视图中的项数来减少绑定的数量。可以使用ng-repeat上的limitTo过滤器对数据进行分页。
How to improve performance of ngRepeat over a huge dataset (angular.js)?上的一个例子,那篇文章也有a jsbin example链接。
另外,请确保不使用内联方法提供数据,因为它将在每个$digest上求值。
<li ng-repeat="item in filteredItems()"> // Bad idea, since very often evaluated.
<li ng-repeat="item in items"> // Way to go! 使用bindonce删除绑定
另一个显而易见的解决方案是删除特定元素上的绑定。当然,这意味着更新将不再反映在视图中。
bindonce解决方案所做的远不止是移除双向绑定。基本上,在删除绑定之前,它等待值被绑定一次。最好自己读一读。有关详细信息,请查看the bindonce project。
在顶部列出的文章中,还有关于使用2个列表的模式的信息。一个用于可视化,另一个用作数据源。
使用ng-grid
Ng-grid的优点是它只呈现当前可见的元素。请访问http://angular-ui.github.io/ng-grid/了解更多信息。
Similar ng-if将隐藏的元素从DOM树中完全移除,而ng-show只是将它们保留在适当的位置,但将它们隐藏起来。考虑到ng-if将在再次显示时将原始元素(原始是关键字,而不是更改)的副本放在适当的位置。
过滤提示
这篇文章也有一些关于过滤列表的很好的技巧。
就像使用ng-show隐藏过滤出的元素一样,因为这种方式不需要为数据创建子列表。
以及另一种称为“去抖动用户输入”的技术。最后一个选项是等待过滤,直到用户停止键入。包括a jsfiddle example。
更多
更多技巧可以在链接的文章中找到。那里也有列出的资源,所以这应该是一个很好的起点。我相信这里列出了最明显的一次和快速的胜利。
https://stackoverflow.com/questions/15643467
复制相似问题