基於AngularJS/Ionic框架開發的性能優化


AngularJS作為強大的前端MVVM框架,雖然已經做了很多的性能優化,但是我們開發過程中的不當使用還是會對性能產生巨大影響。

 

下面提出幾點優化的方法:

1. 使用單次綁定符號{{::value}}

AngularJS的性能優化方法之一是減少雙向綁定。我們知道AngularJS的雙向綁定是通過為每個需要雙向綁定的數據對象添加$$watchers,一旦某個scope的數據發生了更新,就觸發臟檢測($digest),深度優先遍歷所有scope對象的$$watchers值的old/new value是否發生變化。所以在開發過程中,我們都要小心判斷創建出的每個$$watchers是否有必要。對於只需要更新一次,以后不管數據層如何變化都不需要更新的數據,使用連續兩個冒號即可在在$$watchers列表中將這個值刪除,即減少了$digest臟檢測循環。

2. ng-repeat優化

第一種方式雖然減少了臟檢測的次數,但是單次綁定的數據畢竟少數,可能加完單次綁定,性能提升並沒有太大。如果我們的代碼中使用了ng-repeat,並且list數量很大時,我們的性能會有很大下降,在移動端尤為明顯。下面幾點是對ng-repeat指令的優化。

  • 使用limitTo來減少第一次加載列表元素的數量,以提高初始化頁面的速度。我們也許有上百上千條數據要顯示,但是屏幕的大小畢竟有限,呈現在用戶眼前的可能就是個1280x800或者360x640大小的屏幕,那我們可以先加載用戶所能看到幾個十幾個列表。limitTo屬性就提供了這樣的功能。
  <li ng-repeat="mail in mails |limitTo:loadMailLimitTo"></li>
  • 使用track by屬性。比如我們有下面一段代碼
<ul>
    <li ng-repeat="mail in mails">
        {{mail.id}}:{{mail.title}}
    </li>
</ul>  

如果我們想更新mails里面的值,我們可能會這么做:

1
$scope.mails = newMailListFromServer;

上一行代碼會告訴ng-repeat去刪除掉所有的li元素,再去重新生成一套新的li,這意味着大量的DOM操作,尤其當li元素里面有 復雜的邏輯判斷和雙向綁定數據。這是因為ng-repeat在創建時會給每個mail加上$hashkey屬性,並時時跟蹤,一旦mails元素替換成服務器 返回的對象,即時他們完全一樣,由於他們沒有$hashkey,所以ng-repeat不會知道他們是一樣的元素。而通過如下的改動:

<li ng-repeat="mail in mails track by mail.id"></li>

ng-repeat會跟蹤我們創建的mail.id去判斷是否為新的元素。這樣就減少了大量的DOM刪減添加操作。
需要注意的是,如果limitTo和track by一起使用的時候,需要把track by放到最后,如

<li ng-repeat="mail in mails | limitTo:loadMailLimitTo track by mail.id"></li>
  • 如果有引入ionic框架,可以使用collection-repeat替代ng-repeat。

collection-repeat是ionic框架自己的一套顯示list的指令,原理在於不論list有多大,頁面最多只有一定數量的item,這個item數量的大小是通過屏幕高度和單個item的高度計算出來的。滑動列表時通過更新item元素的頁面內容和位置來呈現所有的items。所以在大數量級的list呈現上,collection-repeat會比ng-repeat性能好很多。但是需要注意的是,由於collection-repeat是通過時時更新滑動位置的item內容來實現的,所以在item內部使用第一個方法的單次綁定方式,滑動后會造成頁面混亂的情況。

 

3. 減少html頁面中的filter

原因是每當filter執行時,都會走兩次$digest cycle,一次是scope中有數據改動,一次是查看是否有更多的改動需要更新數據。當數據量很大時對性能會有很大影響。我們可以在初始化時就格式化好數據,比如賦值到view層之前,在我們的js代碼里使用angular提供的$filter provider來預處理我們的數據。

 

4. ng-if替代ng-show/ng-hide

原因是ng-if與ng-show/ng-hide的不同之處在於,ng-if在等於false時會把元素從DOM中移除,所以所有綁在該元素上的handler會一同失效。而ng-show/ng-hide不會移除DOM元素,而是使用css style去隱藏/顯示DOM元素,所以handlers會一直存在。

 

5. $scope.$apply()和$scope.$digest()

我們會用到上面兩種去執行一次臟檢測,刷新頁面數據。區別就是$scope.$apply()會從$rootscope開始,深度優先遍歷執行$digest循環,而$scope.$digest會從當前scope開始,往下層scope遍歷臟檢測。如果只是期望當前scope的數據更新,而不涉及到parent $scope,則可以使用$scope.$digest()。

 

6. angular animate

如果我們的項目引入了angular-animate.js的模塊,那么在大部分使用了指令的元素上,animate里面的代碼都會被執行,不管當前元素是否有應用css動畫樣式。這對我們頁面上如果有大量數據頻繁滑動,隱藏顯示的時候會有比較明顯的性能問題。如果我們對當前scope並沒有漸入漸出等動畫效果的時候,可以在當前scope初始化時加上$animate.enabled(false);當然,我們也可以對某個元素進行禁止動畫的動作:$animate.enabled(element, false);

 

7. ionicSlideBox優化(只針對使用了ionic框架的項目)

  • 初始化slidebox時先初始化顯示中間的首先顯示在用戶面前的slide,其他的slide可以在$timeout里面延遲初始化。思想和ng-repeat的limitTo比較類似。
  • slidebox的滑動速度在ionic框架中默認速度是300ms滑完一個slide,通過改變這個速度來使滑動更快速。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM