标签:
谈起angular的脏检查机制(dirty-checking)
, 常见的误解就是认为: ng是定时轮询去检查model是否变更。
其实,ng只有在指定事件触发后,才进入$digest cycle
:
ng-click
)$http
)$location
)$timeout
, $interval
)$digest()
或$apply()
参考《mastering web application development with angularjs》 P294
传统的JS MVC框架, 数据变更是通过setter去触发事件,然后立即更新UI。
而angular则是进入$digest cycle
,等待所有model都稳定后,才批量一次性更新UI。
这种机制能减少浏览器repaint次数,从而提高性能。
参考《mastering web application development with angularjs》 P296
另, 推荐阅读: 构建自己的AngularJS,第一部分:Scope和Digest
$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~309var 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 %}
$digest cycle
, 并从$rootScope开始遍历(深度优先)检查数据变更。$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
在$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
, 参见angular/angular.js#4574以DOM为中心
的思维,拥抱以数据为中心
的思维。参见 > 参见:http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background > 翻译: http://blog.jobbole.com/46589/AngularJS性能优化心得,自己踩过的抗,及一些别人的经验(转哦)
标签:
原文地址:http://www.cnblogs.com/GoodPingGe/p/4655760.html