谈起angular的脏检查机制(dirty-checking)
, 常见的误解就是认为: ng是定时轮询去检查model是否变动。
其实,ng只有在指定事件触发后,才进入$digest cycle
: javascript
ng-click
)$http
)$location
)$timeout
, $interval
)$digest()
或$apply()
参考《mastering web application development with angularjs》 P294java
传统的JS MVC框架, 数据变动是经过setter去触发事件,而后当即更新UI。
而angular则是进入$digest cycle
,等待全部model都稳定后,才批量一次性更新UI。
这种机制能减小浏览器repaint次数,从而提升性能。jquery
参考《mastering web application development with angularjs》 P296
另, 推荐阅读: 构建本身的AngularJS,第一部分:Scope和Digestgit
$scope.$watch(watchExpression, modelChangeCallback)
, watchExpression能够是String或Function。console.log
也很耗时,记得发布时干掉它。(用grunt groundskeeper)ng-if vs ng-show
, 前者会移除DOM和对应的watchbindonce
)
参考《mastering web application development with angularjs》 P303~309angularjs
var unwatch = $scope.$watch("someKey", function(newValue, oldValue){ //do sth... if(someCondition){ //当不须要的时候,及时移除watch unwatch(); } });
避免深度watch, 即第三个参数为truegithub
参考《mastering web application development with angularjs》 P313web
减小watch的变量长度
以下,angular不会仅对{{variable}}
创建watcher,而是对整个p标签。
双括号应该被span包裹,由于watch的是外部elementchrome
参考《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>
$digest cycle
, 并从$rootScope开始遍历(深度优先)检查数据变动。参考《mastering web application development with angularjs》 P308app
$timeout
里面延迟执行。$apply
。$http.get('http://path/to/url').success(function(data){ $scope.name = data.name; $timeout(function(){ //do sth later, such as log }, 0, false); });
$evalAsync
vs $timeout
$evalAsync
, 会在angular操做DOM以后,浏览器渲染以前执行。$evalAsync
, 会在angular操做DOM以前执行,通常不这么用。$timeout
,会在浏览器渲染以后执行。$scope.dataList = convert(dataFromServer)
刷新数据时,咱们常这么作:$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)
在$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); });
$broadcast
会遍历scope和它的子scope,而不是只通知注册了该事件的子scope。$emit
, 参见https://github.com/angular/angular.js/issues/4574以DOM为中心
的思惟,拥抱以数据为中心
的思惟。参见