如何加速AngularJS应用程序?

时间:2013-03-26 17:19:05

标签: angularjs performance

我有一个带有分页网格的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',这显然是另一个主题)?

11 个答案:

答案 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(分页)

减少数据

一个更明显的解决方案是通过减少视图中的项目数来减少绑定量。可以使用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

删除绑定

另一个明显的解决方案是删除特定元素的绑定。当然这意味着更新不会再反映在视图中。

bindonce 解决方案不仅仅是删除2路绑定。基本上它在删除绑定之前等待绑定值一次。最适合自己阅读。查看the bindonce project了解详情。

在顶部列出的文章中,还有关于使用2个列表的模式的信息。一个用于可视化,一个用作数据源。

使用ng-grid

Ng-grid的优点是它只呈现当前可见的元素。阅读更多http://angular-ui.github.io/ng-grid/

类似ng-if完全从DOM树中删除隐藏的元素,而ng-show仅将它们保留在原位但隐藏。考虑到ng-if会在再次显示时将原始副本(原始是关键,而不是更改)放在原位。

过滤提示

该文章还提供了一些过滤列表的重要提示。

与使用ng-show隐藏已过滤的元素一样,因为这样就不必创建数据的子列表。

另一种技术被称为&#34;去抖用户输入&#34;。最后一个选项是等待过滤,直到用户停止输入。包括a jsfiddle example

更多

可以在链接文章中找到更多提示。那里也列出了资源,所以应该是一个很好的起点。我相信这里列出了最明显的优势和快速获胜。

另一个不错的文章是How does data binding work in AngularJS?

答案 3 :(得分:13)

有点晚了但也许这适合你:

https://github.com/Pasvaz/bindonce

您可以在那些无意更改的绑定上使用它,因此$ digest将不再处理它们。

答案 4 :(得分:7)

在1.3和更高的角度你可以使用::绑定一次,不需要使用其他3方js

<li ng-repeat="item in :: items">

如果项目不会改变,那么你可以将它们绑定一次

答案 5 :(得分:1)

当数据网格组件中的侦听器数量超过1000+时,我遇到了性能问题。

我使用一个使用react.js构建我的视图的指令解决了这个问题。 该指令暴露了更新功能。

每次数据发生变化(在控制器中)时,更新功能触发了指令,然后react.js引擎有效地进行了渲染。

我知道在角度项目中使用第二个主要框架是一个很大的开销,这不是真正的数据绑定魔法。但它的工作速度要快得多。

最终我停止使用angular.js并转移到react.js + FLUX。我认为它更好,但我知道它不容易从角度转移,但值得。

Angular directive that uses react.js

答案 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

提高效果