談起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爲中心
的思惟,擁抱以數據爲中心
的思惟。參見