無論你正在編寫一箇舊的應用程式還是在一個大型應用中採用AngularJS,效能是一個重要的方面。瞭解是什麼原因導致AngularJS應用程式慢下來非常重要,要知道,在開發過程中做出權衡是很重要的。本文將介紹一些AngularJS比較常見的效能問題,以及優化的建議。
2. 效能測試工具
本文采用jsPerf http://jsperf.com/ 效能測試的基準。
3.軟體效能
評價軟體效能有兩個基本的因素:
首先是演算法的時間複雜度。一個簡單的例子就是線性搜尋和二分檢索有著非常顯著的效能差距。
第二個軟體緩慢的原因被稱為空間複雜度。這是一臺電腦需要多少“空間”或記憶體執行你的應用程式。記憶體需求越多,執行速度就越慢。
4 Javascript的效能
有些效能問題不僅僅是Angular帶來的,而是JavaScript本來就有的。
4.1 迴圈
避免在迴圈內部呼叫函式,可以移到外部呼叫。
var sum = 0; for(var x = 0; x < 100; x++){ var keys = Object.keys(obj); sum = sum + keys[x]; }
上面的方面明顯沒有下面的快:
var sum = 0; var keys = Object.keys(obj); for(var x = 0; x < 100; x++){ sum = sum + keys[x]; }
4.2 DOM訪問
在獲取DOM元素時要注意
angular.element('div.elementClass')
這種方式是非常昂貴的。其實這在AngularJS中並不會引起太大的問題。但是留意一下是有好處的。DOM樹要小,DOM的訪問要儘可能的少。
4.3變數作用範圍垃圾回收
把你的變數作用範圍限制地越緊密越好,這樣垃圾回收器就可以更快地回收空間。注意下面的問題:
function demo(){ var b = {childFunction: function(){ console.log('hi this is the child function') }; b.childFunction(); return b; }
當這個函式終上了,這裡就沒有到b的引用。b就會被回收了。但是如果有這樣一行:
var cFunc = demo();
這個引用就會阻止垃圾回收。要儘量避免這類引用。
4.4 陣列和物件
這裡有很多點:
比如:
for (var x=0; x<arr.length; x++) { i = arr[x].index; }
比這一種快一點(注*arr為陣列, obj為json物件)
for (var x=0; x<100; x++) { i = obj[x].index; }
比這一種更快一點
var keys = Object.keys(obj); for (var x = 0; x < keys.length; x++){ i = obj[keys[x]].index; }
測試: http://jsperf.com/array-vs-object-perf-demo
5重要的概念
我們已經討論過有關JavaScript的效能,現在有必要看一看AngualrJS中的核心概念,看看它究竟是怎麼運作的。
5.1 域(Scopes)和更新週期(DigestCycle)
Angular的域本質上是一些JavaScript物件,它們從一些預定義的物件繼承而來。基本上,小的域比大的域執行要快。
換句話說,每建立一個新的域,都會給垃圾回收器新增更多待回收的內容。
在寫AngularJS應用中尤其要注意的一個核心概念和效能影響方面是更新週期(DigestCycle)。實際上每一個域都會存放一個由方法組成的陣列 $$watchers。
每當域中的一個值(屬性)或繫結的DOM,如ng-repeat,ng-switch 和 ng-if 等等,呼叫 $watch時,一個函式(function)就會新增到相對應域中的$$watchers陣列佇列中。
當域中的值發生改變時,在$$watchers中所有的watchers函式都會被觸發呼叫。並且當它們的任何一個修改了域中的某個值時,它們會被再次觸發執行。
這個過程會一直迴圈下去直到$$watcher陣列佇列中不再做任何更改或丟擲異常為止。
更外如果任何程式碼執行$scope.$apply(),都會觸發更新週期。
最後一點是$scope.evalAsync() 會在一個非同步呼叫中執行,並且在當前和下個執行週期中,不會呼叫其的更新週期。
6. 在設計Angular時應該遵守的一般準則
6.1大型物件和伺服器呼叫
所以這些都告訴了我們什麼?首先我們要儘可能地簡化我們的物件。當物件是從伺服器返回時,這一點尤為重要。
直接將資料庫中的一行轉換成物件只是臨時性方案,因此不要使用.toJson().
只需要把Angular需要的屬性值返回回來。
6.2 監視函式(Watching Functions)
另一個常見的問題是為觀察者繫結的函式。不要將任何東西(ng-show,ng-repeat等等)直接繫結到一個函式。不要直接監視任何函式的返回值。該函式會在每個更新週期都執行,可能會降低你應用的速度。
6.3 監視物件(WatchingObjects)
同樣,Angular提供了第三個可選引數來監視整個物件的改動。將呼叫$watch的第三個引數設為true。這是一個非常可怕的想法。一個更好的解決辦法是依靠服務和物件的引用,監視域之間的變化。
原文地址: airpair.com
相關閱讀
評論(1)