angular性能优化心得
原文出处
脏数据检查 != 轮询检查更新
谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更。
其实,ng只有在指定事件触发后,才进入$digest cycle:
- DOM事件,譬如用户输入文本,点击按钮等。(
ng-click) - XHR响应事件 (
$http) - 浏览器Location变更事件 (
$location) - Timer事件(
$timeout,$interval) - 执行
$digest()或$apply()

参考《mastering web application development with angularjs》 P294
$digest后批量更新UI
传统的JS MVC框架, 数据变更是通过setter去触发事件,然后立即更新UI。
而angular则是进入$digest cycle,等待所有model都稳定后,才批量一次性更新UI。
这种机制能减少浏览器repaint次数,从而提高性能。
参考《mastering web application development with angularjs》 P296
另, 推荐阅读: 构建自己的AngularJS,第一部分:Scope和Digest
提速 $digest cycle
关键点
- 尽少的触发$digest (P310)
- 尽快的执行$digest
优化$watch
$scope.$watch(watchExpression, modelChangeCallback), watchExpression可以是String或Function。- 避免watchExpression中执行耗时操作,因为它在每次$digest都会执行1~2次。
- 避免watchExpression中操作dom,因为它很耗时。
console.log也很耗时,记得发布时干掉它。(用grunt groundskeeper)ng-if vs ng-show, 前者会移除DOM和对应的watch- 及时移除不必要的$watch。(angular自动生成的可以通过下文介绍的
bindonce)
参考《mastering web application development with angularjs》 P303~309
var unwatch = $scope.$watch("someKey", function(newValue, oldValue){
//do sth...
if(someCondition){
//当不需要的时候,及时移除watch
unwatch();
}
});
避免深度watch, 即第三个参数为true
参考《mastering web application development with angularjs》 P313
减少watch的变量长度
如下,angular不会仅对{{variable}}建立watcher,而是对整个p标签。
双括号应该被span包裹,因为watch的是外部element参考《mastering web application development with angularjs》 P314
<p>plain text other {{variable}} plain text other</p>
//改为:
<p>plain text other <span ng-bind='variable'></span> plain text other</p>
//或
<p>plain text other <span>{{variable}}</span> plain text other</p>
$apply vs $digest
- $apply会使ng进入
$digest cycle, 并从$rootScope开始遍历(深度优先)检查数据变更。 - $digest仅会检查该scope和它的子scope,当你确定当前操作仅影响它们时,用$digest可以稍微提升性能。
参考《mastering web application development with angularjs》 P308
延迟执行
- 一些不必要的操作,放到
$timeout里面延迟执行。 - 如果不涉及数据变更,还可以加上第三个参数false,避免调用
$apply。 - 对时间有要求的,第二个参数可以设置为0。
$http.get('http://path/to/url').success(function(data){
$scope.name = data.name;
$timeout(function(){
//do sth later, such as log
}, 0, false);
});
$evalAsyncvs$timeout- http://stackoverflow.com/questions/17301572/angularjs-evalasync-vs-timeout
- directive中执行的
$evalAsync, 会在angular操作DOM之后,浏览器渲染之前执行。 - controller中执行的
$evalAsync, 会在angular操作DOM之前执行,一般不这么用。 - 而使用
$timeout,会在浏览器渲染之后执行。
优化ng-repeat
限制列表个数
- 列表对象的数据转换,在放入scope之前处理。如
$scope.dataList = convert(dataFromServer) - 可以使用ngInfiniteScroll来做无限滚动。
使用 track by
刷新数据时,我们常这么做:$scope.tasks = data || [];,这会导致angular移除掉所有的DOM,重新创建和渲染。
若优化为ng-repeat="task in tasks track by task.id后,angular就能复用task对应的原DOM进行更新,减少不必要渲染。
参见:http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by
使用单次绑定
我们都知道angular建议一个页面最多2000个双向绑定,但在列表页面通常很容易超标。
譬如一个滑动到底部加载下页的表格,一行20+个绑定, 展示个100行就超标了。
下图这个只是一个很简单的列表,还不是表格,就已经这么多个了:
但其实很多属性显示后是几乎不会变更的, 这时候就没必要双向绑定了。(不知道angular为何不考虑此类场景)
如下图,改为bindonce或angular-once后减少了很多:
update:
1.3.0b10开始支持内建单次绑定, {{::variable}}
设计文档:http://t.cn/RvIYHp9
commit: http://t.cn/RvIYHpC
目前该特性的性能似乎还有待优化(2x slower)
慎用filter
在$digest过程中,filter会执行很多次,至少两次。
所以要避免在filter中执行耗时操作。
参考《mastering web application development with angularjs》 P136
angular.module('filtersPerf', []).filter('double', function(){
return function(input) {
//至少输出两次
console.log('Calling double on: '+input);
return input + input;
};
});
可以在controller中预先处理
//mainCtrl.js
angular.module('filtersPerf', []).controller('mainCtrl', function($scope, $filter){
$scope.dataList = $filter('double')(dataFromServer);
});
慎用事件
- 减少事件广播,使用双向数据绑定或共享service等方法来代替。
$broadcast会遍历scope和它的子scope,而不是只通知注册了该事件的子scope。- 一个优化方式是使用
$emit, 参见https://github.com/angular/angular.js/issues/4574 - 1.2.7版本对事件做过一个优化,参见https://github.com/angular/angular.js/blob/master/CHANGELOG.md#127-emoji-clairvoyance-2014-01-03
- 对高频的事件做缓冲限速,避免触发太频繁。
directive
- 跟scope数据无关的操作放在compile阶段,它只执行一次。
- 除了directive外其他地方,特别是controller里面不要操作dom, 尤其是绑定到scope后,便是灾难。
- 改变以前使用JQuery那样
以DOM为中心的思维,拥抱以数据为中心的思维。参见
使用Batarang来分析性能
- AngularJS Batarang是官方提供的chrome插件

angular性能优化心得的更多相关文章
- Angular性能优化实践——巧用第三方组件和懒加载技术
应该有很多人都抱怨过 Angular 应用的性能问题.其实,在搭建Angular项目时,通过使用打包.懒加载.变化检测策略和缓存技术,再辅助第三方组件,便可有效提升项目性能. 为了帮助开发者深入理解和 ...
- AngularJS性能优化心得,自己踩过的抗,及一些别人的经验(转哦)
脏数据检查 != 轮询检查更新 谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更.其实,ng只有在指定事件触发后,才进入$ ...
- js查重去重性能优化心得
概述 今天产品反映有个5000条数据的页面的保存按钮很慢,查看代码看到是因为点击保存按钮之后,进行了查重操作,而查重操作是用2个for循环完成了,时间复杂度是O(n^2).没办法,只能想办法优化一下了 ...
- Angular 1 深度解析:脏数据检查与 angular 性能优化
TL;DR 脏检查是一种模型到视图的数据映射机制,由 $apply 或 $digest 触发. 脏检查的范围是整个页面,不受区域或组件划分影响 使用尽量简单的绑定表达式提升脏检查执行速度 尽量减少页面 ...
- Angular 的性能优化
目录 序言 变更检查机制 性能优化原理 性能优化方案 小结 参考 序言 本文将谈一谈 Angular 的性能优化,并且主要介绍与运行时相关的优化.在谈如何优化之前,首先我们需要明确什么样的页面是存在性 ...
- C#中那些[举手之劳]的性能优化
隔了很久没写东西了,主要是最近比较忙,更主要的是最近比较懒...... 其实这篇很早就想写了 工作和生活中经常可以看到一些程序猿,写代码的时候只关注代码的逻辑性,而不考虑运行效率 其实这对大多数程序猿 ...
- C#程序员应该养成的程序性能优化写法
转载一个别人的文章 隔了很久没写东西了,主要是最近比较忙,更主要的是最近比较懒…… 其实这篇很早就想写了 工作和生活中经常可以看到一些程序猿,写代码的时候只关注代码的逻辑性,而不考虑运行效率 其实这对 ...
- 之前做web性能优化的一些个人心得
一个web项目后期的维护主要在于性能方面.数据吞吐量一旦增大各种bug都出来了.那些通过硬件<数据库分表,数据库主从分离,读写分离>等的一些手段此处就不多说了.本文主要在编码方面做一个性能 ...
- 【前端构建】WebPack实例与前端性能优化
计划把微信的文章也搬一份上来. 这篇主要介绍一下我在玩Webpack过程中的心得.通过实例介绍WebPack的安装,插件使用及加载策略.感受构建工具给前端优化工作带来的便利. 壹 | Fisrt 曾几 ...
随机推荐
- java Cookie 获取历史记录列表(三)
/** * 获取Cookie里面的东西 */ protected List<String> getCookieList() { Cookie[] cookies = null; Cooki ...
- 【hive】cube和rollup函数
cube 数据立方体(Data Cube),是多维模型的一个形象的说法.(关于多维模型这里不讲述,在数据仓库设计过程中还挺重要的,有兴趣自行查阅) 立方体其本身只有三维,但多维模型不仅限于三维模型,可 ...
- HDU 2612 Find a way bfs 难度:1
http://acm.hdu.edu.cn/showproblem.php?pid=2612 bfs两次就可将两个人到达所有kfc的时间求出,取两人时间之和最短的即可,这个有点不符合实情,题目应该出两 ...
- [Java] Eclipse下导入外部jar包的3种方式
我们在用Eclipse开发程序的时候,经常要用到第三方jar包.引入jar包不是一个小问题,由于jar包位置不清楚,而浪费时间.下面配图说明3种Eclipse引入jar包的方式. 1.最常用的普通 ...
- Java 复制一个文件到另外一个目录下
因为项目部署在jboss上面,在上传一些图片的时候,把他上传到当前项目的下,比如:(这里是以Windows服务器为例的,当然linux也是一样的) D:\jboss-eap-6.4\domain\se ...
- es6 中的generator函数控制流程
Generator函数跟普通函数的写法有非常大的区别: 一是,function关键字与函数名之间有一个星号: 二是,函数体内部使用yield语句,定义不同的内部状态(yield在英语里的意思就是“产出 ...
- 使用RESTful风格整合springboot+mybatis
说明: 本文是springboot和mybatis的整合,Controller层使用的是RESTful风格,数据连接池使用的是c3p0,通过postman进行测试 项目结构如下: 1.引入pom.xm ...
- SQL Server2008 R2开启远程连接总结
============================== SQL Server2008 R2开启远程连接(最全总结) ============================== 安装过程:适用W ...
- flask第二十三篇——模板【5】过滤器
请关注微信公众号:自动化测试实战 过滤器——format格式化 flaskDemo.py # coding: utf-8 from flask import Flask, render_templat ...
- 关于CCRANDOM_0_1
CCRANDOM_0_1的范围是[0,1)包括0但不包括1 CCRANDOM_0_1() * 1400.0f / 100.0f是0-13 另外每次随机都是相同的数,要随机下种子 srand((unsi ...