我是一个刚接触AngularJs的新手(尽管我不是web开发的新手),所以请保持怀疑的态度来看这11条建议。我阅读了很多关于如何提升Angular性能的文章,下面就是我的相关总结。
内容列表:
- 最少化/避免 监听器(watchers)
- 避免使用ng-repeat。如果你不得不使用ng-repeat的话,请使用分页或者页面滚动。
- 如果可能的话,只绑定一次
- 用$watchCollection 替代 $watch(加入第三个参数)
- 避免使用重复的过滤器
- debounce ng-model
- 用ng-if 替代ng-show(但是请确认ng-if是否更适合你的项目)
- 用console.time来检测你的函数
- 用本地的JavaScript或者Lodash
- 用Batarang来检测你的监听器
- 用Chrome Timeline和Profiler 来寻找性能的瓶颈
1.最少化/避免 监听器(watchers)
通常来说,如果你的Angular应用比较慢,那么意味着,你有太多的监听器(watcher),或者是监听器负担超过了本身的职责。
Angular使用dirty-checking来跟踪应用中的所有的改变,这意味着,Angular将遍历所有的监听器(watcher)去检测是否他们需要更新。如果一个监听器又依赖于另外一个监听器,Angular将会不得不再次运行一遍$digest循环,来确保所有的改变都被处理。Angular将会持续不断的进行$digest循环,直到所有的监听器(watcher)都被更新,并且应用趋于稳定。
尽管在浏览器中运行JavaScript非常之快,但是在Angular中很容易添加很多的监听器,以至于你的Angular应用变得很慢。
当实现或者重构你的Angular应用时,请记住以下几点:
1.监听器(watcher)在以下情况下建立:
- $scope.$watch
- {{}}绑定数据
- 大多数的指令(例如:ng-show)
- scope变量 scope:{bar:'='}
- 过滤器{{value|myFilter }}
- ng-repeat
2.监听器运行在:
- 用户操作(ng-click).
- ng-change
- ng-model
- $http 事件
- $q promise API
- $timeout
- $interval
- 手动调用$scope.apply和$digest.digest
2.避免使用ng-repeat。如果你不得不使用ng-repeat的话,请使用分页或者页面滚动。
这是我们应用的最大改进(This was the biggest win for our app)。我这里并不会讲太多细节,但是我找到离开很多有用的文章。
另外关于滚动(infinite scroll),如果可能的话确保使用track by。
举例说明:唯一的id,就是在使用ng-repeat 传给 track by 比较好的值
<li ng-repeat="Task in Tasks track by Task.Id></li>
3.如果可能的话,只绑定一次
(可能被墙,我是开着VPN访问的)
如果你用的是1.3之前的版本,你可以用下面这个库实现相同的效果。
4.用$watchCollection 替代 $watch(加入第三个参数)
只有两个参数$watch 运行速度很快。然而,Angular对这个函数支持第三个参数,例如:$watch('value',function(){},true)。第三个参数,告诉Angular执行深度检查,意味着检测对象的每个属性,这样成本非常高。
为了解决这种性能问题,Angular增加了 $watchCollection('value',function(){})。$watchCollection表现的像$watch带有第三个参数一样,除了它只检测对象属性的第一层,因而会极大地提升性能。
官方文档:
相关博客地址:
5.避免重复的过滤器,并且缓存数据
一次绑定在有过滤器的时候表现的不是很好。得像办法让它工作,但是我认为把它直接赋给一个变量会更加的清晰和直观(或者如果你处理很多变量的话,把它设为对象的一个属性)。
例如:
{{'DESCRIPTION' | translate }}
被替换为:
-JS
$scope.description: $translate.instant('DESCRIPTION')
-HTML
{{::description}}
或者:
{{step.time_modified | timeFormatFilter}}
- JavaScript
vartimeFormatFilter=$filter('timeFormatFilter'); step.time_modified=timeFormatFilter(step.time_modified);
- HTML
{{::Path.time_modified}}
6.限制ng-model更新频率(debounce ng-model)
如果你知道一个ng-model有很多改变的话,你可以de-bounce input输入框。
这会确保$digest循环触发的次数不多于250ms一次。
7.使用ng-if替代ng-show(但是必须适合你自己的项目)
ng-if
会移除DOM元素,并且在需要它的时候,再重新创建。
你可能使用ng-show 显示或者隐藏一个元素,在95%的情况下,ng-if是更加适合的方式。
8.使用console.time来检测函数
console.time
是一个非常好的API,并且我发现当测试Angular性能的时候,它非常有用。在我的代码里,我调用了很多这个函数,来帮助我确定我重构的Angular的性能。
https://developer.mozilla.org/en-US/docs/Web/API/Console/time
API这样使用:
console.time("TimerName"); //Some code console.timeEnd("TimerName");
这是一个简单的例子:
console.time("TimerName"); setTimeout(function(){ console.timeEnd("TimerName"); },100); //In console $: TimerName: 100.324ms
Note:如果console.time不能满足你的需求的话,你可以使用 preformance.now。如果你选择了这种方式,你必须自己写自己的方法。
https://docs.google.com/presentation/…
totalTime = 0; count = 0; var someFunction = function() { var thisRunStartTime = performance.now(); count++; // some code // some more code totalTime += performance.now() - thisRunStartTime; }; console.log("Average time: " + totalTime/count);
原文地址:http://www.alexkras.com/11-tips-to-improve-angularjs-performance/#ng-repeat
原文链接:https://www.f2er.com/angularjs/149571.html