我有一个带有分页网格的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
除此之外:'Object.observe()'是否有可能在将来加快速度(忽略'initDateWidget',这显然是另一个主题)?
答案 0 :(得分:28)
你可以做的事情将最大限度地加速你的Angular应用程序,尽可能减少那些绑定。一种方法是创建一个指令,使用DOM操作而不是使用ng-repeats为您构建表。这将减少您必须处理的整体手表的数量,并使这个$ digest的速度更快。
我知道这样做很难看,但是Angular并不真正意味着设置3000+绑定。因为它做了一个摘要而且它不是一个观察者模式,所以如果有很多人设置它会让事情变慢。
你甚至可以使用混合方法,你仍然使用ng-repeat,但所有值都放在DOM中,并使用自定义指令中的直接DOM操作,从而避免了所有绑定。
答案 1 :(得分:21)
如果您还没有这样做,请安装AngularJS Chrome插件,Batarang,它将帮助您确定哪些绑定导致您的悲伤。 https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en
正如另一个答案所暗示的那样,您正在寻找的是一个小型无限滚动设置,您绑定的模型是您在屏幕上显示的子集。
ng-grid组件实现了这一点,可能值得直接使用它或窃取技术。 http://angular-ui.github.com/ng-grid/
答案 2 :(得分:19)
This post about angularJS performance on large lists概述了性能调优的选项。
以上答案(Batarang插件除外)也在其中提及。这只是该文章中提示的概述。
一个更明显的解决方案是通过减少视图中的项目数来减少绑定量。可以使用limitTo
上的ng-repeat
过滤器完成数据分页。
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 解决方案不仅仅是删除2路绑定。基本上它在删除绑定之前等待绑定值一次。最适合自己阅读。查看the bindonce project了解详情。
在顶部列出的文章中,还有关于使用2个列表的模式的信息。一个用于可视化,一个用作数据源。
Ng-grid
的优点是它只呈现当前可见的元素。阅读更多http://angular-ui.github.io/ng-grid/。
类似ng-if
完全从DOM树中删除隐藏的元素,而ng-show
仅将它们保留在原位但隐藏。考虑到ng-if
会在再次显示时将原始副本(原始是关键,而不是更改)放在原位。
该文章还提供了一些过滤列表的重要提示。
与使用ng-show
隐藏已过滤的元素一样,因为这样就不必创建数据的子列表。
另一种技术被称为&#34;去抖用户输入&#34;。最后一个选项是等待过滤,直到用户停止输入。包括a jsfiddle example。
可以在链接文章中找到更多提示。那里也列出了资源,所以应该是一个很好的起点。我相信这里列出了最明显的优势和快速获胜。
答案 3 :(得分:13)
答案 4 :(得分:7)
在1.3和更高的角度你可以使用::绑定一次,不需要使用其他3方js
<li ng-repeat="item in :: items">
如果项目不会改变,那么你可以将它们绑定一次
答案 5 :(得分:1)
当数据网格组件中的侦听器数量超过1000+时,我遇到了性能问题。
我使用一个使用react.js构建我的视图的指令解决了这个问题。 该指令暴露了更新功能。
每次数据发生变化(在控制器中)时,更新功能触发了指令,然后react.js引擎有效地进行了渲染。
我知道在角度项目中使用第二个主要框架是一个很大的开销,这不是真正的数据绑定魔法。但它的工作速度要快得多。
最终我停止使用angular.js并转移到react.js + FLUX。我认为它更好,但我知道它不容易从角度转移,但值得。
答案 6 :(得分:0)
限制手表的数量往往可以走很长的路。以下是有效减少手表数量的技术摘要
http://www.syntaxsuccess.com/viewarticle/547a8ba2c26c307c614c715e
答案 7 :(得分:0)
我在使用大数据的ng-grid时遇到了性能问题,通过将其替换为Angular Grid来解决。该网站上的演示显示它可以轻松管理100,000行。
答案 8 :(得分:0)
我已经和它搏斗了几个星期。我发现有两件事情有很大不同:
(i)一次性约束:尽可能使用一次性绑定;和 (ii)DEBOUNCE:对于不需要立即传播的输入,但可以等待250ms,设置去抖动设置。这对我的大型ng-repeat表格产生了难以置信的差异。我不能强调去抖设置的效果如何。 (见这里:https://docs.angularjs.org/api/ng/directive/ngModelOptions)
答案 9 :(得分:0)
bject.observe()是一种用于将真正的数据绑定引入浏览器的机制。它公开了一种机制,用于观察对象和数组的变化,通知其他人对这些对象所做的突变。
<!DOCTYPE html>
<html>
<head>
<base target="_blank">
<title>Object.observe()</title>
<link rel="stylesheet" href="../css/main.css" />
</head>
<body>
<div id="container">
<h1><a href="https://shailendrapathakbits.wordpress.com/" title="code_lab_by_shail ">code_lab_by_shail</a> Object.observe()</h1>
<p>An object <code>o</code> is created and <code>Object.observe()</code> is called on it.</p>
<p>Three changes are made to <code>o</code> and <code>Object.observe()</code> records these changes as shown below.</p>
<p>Use the console to find out what happens if you make further changes to <code>o</code>: it's defined in global scope.</p>
<p>Call <code>Object.unobserve(o, observer)</code> to stop observing changes.</p>
<p id="data" style="font-size: 14px;"></p>
<script src="js/main.js"></script>
<a href="https://github.com/shailendra9/objectobserver/blob/master/index.html" title="View source for this page on GitHub" id="viewSource">View source on GitHub</a>
</div>
<script src="../js/lib/ga.js"></script>
</body>
</html>
答案 10 :(得分:0)
您还可以通过Disabling Debug Data
提高效果