AngularJS性能优化心得,自己踩过的抗,及一些别人的经验(转哦)
脏数据检查 != 轮询检查更新
谈起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不会仅对{% raw %}{{variable}}{% endraw %}建立watcher,而是对整个p标签。
双括号应该被span包裹,因为watch的是外部element参考《mastering web application development with angularjs》 P314
{% raw %}
<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>
{% endraw %}
$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
慎用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, 参见angular/angular.js#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为中心的思维,拥抱以数据为中心的思维。参见 > 参见:http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background > 翻译: http://blog.jobbole.com/46589/
AngularJS性能优化心得,自己踩过的抗,及一些别人的经验(转哦)的更多相关文章
- angular性能优化心得
原文出处 脏数据检查 != 轮询检查更新 谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更.其实,ng只有在指定事件触发后 ...
- AngularJS性能优化
几个概念 域$scope和更新周期DigestCycle AngularJS的域本质上是一些JavaScript对象,它们从一些预定义的对象继承而来.基本上,小的域比大的域运行要快. 每创建一个新的域 ...
- js查重去重性能优化心得
概述 今天产品反映有个5000条数据的页面的保存按钮很慢,查看代码看到是因为点击保存按钮之后,进行了查重操作,而查重操作是用2个for循环完成了,时间复杂度是O(n^2).没办法,只能想办法优化一下了 ...
- C#中那些[举手之劳]的性能优化
隔了很久没写东西了,主要是最近比较忙,更主要的是最近比较懒...... 其实这篇很早就想写了 工作和生活中经常可以看到一些程序猿,写代码的时候只关注代码的逻辑性,而不考虑运行效率 其实这对大多数程序猿 ...
- C#程序员应该养成的程序性能优化写法
转载一个别人的文章 隔了很久没写东西了,主要是最近比较忙,更主要的是最近比较懒…… 其实这篇很早就想写了 工作和生活中经常可以看到一些程序猿,写代码的时候只关注代码的逻辑性,而不考虑运行效率 其实这对 ...
- SQL Server数据库性能优化之索引篇【转】
http://www.blogjava.net/allen-zhe/archive/2010/07/23/326966.html 性能优化之索引篇 近期项目需要, 做了一段时间的SQL Server性 ...
- SQL Server数据库性能优化之SQL语句篇【转】
SQL Server数据库性能优化之SQL语句篇http://www.blogjava.net/allen-zhe/archive/2010/07/23/326927.html 近期项目需要, 做了一 ...
- 基于AngularJS/Ionic框架开发的性能优化
AngularJS作为强大的前端MVVM框架,虽然已经做了很多的性能优化,但是我们开发过程中的不当使用还是会对性能产生巨大影响. 下面提出几点优化的方法: 1. 使用单次绑定符号{{::value}} ...
- 【Unity游戏开发】性能优化之在真机上开启DeepProfile与踩坑
一.引子 最近马三入职了新公司,平时除了负责编辑器开发之外还要做一些游戏性能优化方面的工作.在这里首先给大家安利一下Unity官方的性能测试分析工具URP ,这个工具目前是免费,测试的过程中也不需要接 ...
随机推荐
- Flask 之 宏
宏 对宏(macro)的理解: 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用 需要在多处重 ...
- 【深度学习 01】线性回归+PyTorch实现
1. 线性回归 1.1 线性模型 当输入包含d个特征,预测结果表示为: 记x为样本的特征向量,w为权重向量,上式可表示为: 对于含有n个样本的数据集,可用X来表示n个样本的特征集合,其中行代表样本,列 ...
- GitHub还能这样玩,这次我真是开了眼了
哈喽,大家好,我是指北君. 我会一直在"开源指北"公众号给大家分享各种有趣. 实用与最前沿的开源项目,还有各种互联网干货, 今天主要给大家分享一下GitHub的一些使用技巧,帮助你 ...
- var、let和const区别
var.let和const区别 变量提升问题 var声明的变量存在变量提升,而let与const声明的变量不存在变量提升,但存在暂时性死区 即在预编译阶段,js引擎扫描代码时,遇到变量声明,会把var ...
- Redis 的同步机制了解么?
Redis 可以使用主从同步,从从同步.第一次同步时,主节点做一次 bgsave, 并同时将后续修改操作记录到内存 buffer,待完成后将 rdb 文件全量同步到复制 节点,复制节点接受完成后将 r ...
- Container 在微服务中的用途是什么?
容器是管理基于微服务的应用程序以便单独开发和部署它们的好方法.您可以将 微服务封装在容器映像及其依赖项中,然后可以使用它来滚动按需实例的微服务, 而无需任何额外的工作.
- 学习Git(二)
常用命令 git add 添加 git status 查看状态 git status -s 状态概览 git diff 对比 git diff --staged 对比暂存区 git commit 提交 ...
- idea问题之"一个或多个listeners启动失败问题"
org.apache.catalina.core.StandardContext.startInternal 一个或多个listeners启动失败,更多详细信息查看对应的容器日志文件之 "A ...
- MATLAB设计模糊控制器并用simulink仿真
一.设计模糊控制器1.1 创建项目文件夹在此路径如图 1.2 打开MATLAB打开MATLAB R2012a切换当前目录为上一步路径,如图 1.3 设计模糊控制器打开模糊控制器设计对话框 根据模糊控制 ...
- visual studio 2019工具里添加开发中命令提示符的方法
最新新装了visual studio 2019,发现默认的没有开发者命令提示符 现将添加步骤描述如下: 从VS2019菜单选择"Tools",然后选择"外部工具" ...