提升AngularJS性能的11条建议

  我是一个刚接触AngularJs的新手(尽管我不是web开发的新手),所以请保持怀疑的态度来看这11条建议。我阅读了很多关于如何提升Angular性能的文章,下面就是我的相关总结。

内容列表:

  1. 最少化/避免 监听器(watchers)
  2. 避免使用ng-repeat。如果你不得不使用ng-repeat的话,请使用分页或者页面滚动。
  3. 如果可能的话,只绑定一次
  4. 用$watchCollection 替代 $watch(加入第三个参数)
  5. 避免使用重复的过滤器
  6. debounce ng-model
  7. 用ng-if 替代ng-show(但是请确认ng-if是否更适合你的项目)
  8. 用console.time来检测你的函数
  9. 用本地的JavaScript或者Lodash
  10. 用Batarang来检测你的监听器
  11. 用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.如果可能的话,只绑定一次


Angular1.3 增加了 ::  以支持一次绑定。总而言之,Angular第一次$digest循环时,会等待一个稳定的值,然后用该值生成DOM元素。然后,Angular会移除监听器,忘记该绑定。


id="cp_embed_QbWJRg" src="http://codepen.io/akras14/embed/QbWJRg?height=268&theme-id=5767&slug-hash=QbWJRg&default-tab=result&user=akras14" scrolling="no" frameborder="0" height="268" allowtransparency="true" allowfullscreen="true" name="CodePen Embed" title="CodePen Embed" class="cp_embed_iframe " style="box-sizing: border-box; max-width: 100%; font-family: Lora, serif; font-size: 18px; line-height: 29.25px; width: 809px; overflow: hidden;">

(可能被墙,我是开着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输入框。
例如有一个像Google这样的搜索输入框,你可以通过设置ng-model的options ng-model-options="{ debounce: 250 }
 这会确保$digest循环触发的次数不多于250ms一次。

7.使用ng-if替代ng-show(但是必须适合你自己的项目)

ng-show  会显示一个DOM元素,使用   display:none  可以隐藏它。

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);


9.对于缓慢的js使用本地js或者Lodash(use native JavaScript or Lodash for slow JavaScript)

我们的应用已经使用了lodash,所有对我来说,不用再选择其他的了。如果lodash没有引入的话,我可能得要用js重写所有的事情。

在我的测试中,我只需要用lodash写一些简单的逻辑,就可以获得极大的性能提升。

Lodash的维护人员 John-David Dalton也是 https://jsperf.com/合作人之一,在性能提升方面有很大的成就,所有我信任他以及他的库。


10.使用Batarabg 来检测你的监听器(watchers)

Batarang是Angular团队开发的一个非常好的工具,并且在我的debugging工作中非常有用。它有很多的有用的功能,对我们性能有用的是性能tab页(performance tab)。

batarang

请确保下载的是稳定的版本:

https://chrome.google.com/webstore/detail/angularjs-batarang-stable/niopocochgahfkiccpjmmpchncjoapek


11.使用chrome的TimeLine 和 Profiler 来找到性能瓶颈

我认为我自己是一个chrome开发工具的忠实用户。在这个项目中,这两种工具都极其的有用。

Tip:如果你使用console.time API(#8),在你的TimeLine中这个时间区域将会被高亮。这样你就可以检测出你所关心的那块的时间。

https://developer.chrome.com/devtools/docs/timeline#user-produced-timeline-events

在TimeLine视图中,60fps线是起关键性作用的,当我启动我们的项目的时候,应用完全生成完毕要至少15秒,用户很难接受这样的应用。

New

经过性能优化,app完全渲染完毕不到2s(注意到时间范围不一样了),让用户感觉到很短的时间内就可以和UI交互。


New




原文地址:http://www.alexkras.com/11-tips-to-improve-angularjs-performance/#ng-repeat

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值