摘要:本文針對的讀者具備性能優化的相關知識雅虎條性能優化原則高性能網站建設指南等擁有實戰經驗。這種機制能減少瀏覽器次數,從而提高性能。僅會檢查該和它的子,當你確定當前操作僅影響它們時,用可以稍微提升性能。
搬運自: http://atian25.github.io/2014/05/09/angular-performace/
臟數據檢查 != 輪詢檢查更新不知不覺,在項目中用angular已經半年多了,踩了很多坑。
趁著放假,把angular的3本書都看了遍,結合這半年的經驗,是該做個總結了。
希望可以給大家帶來啟示,少踩點坑。
本文針對的讀者:
- 具備JavaScript性能優化的相關知識(雅虎14條性能優化原則、《高性能網站建設指南》等)
- 擁有angular實戰經驗。
談起angular的臟檢查機制(dirty-checking), 常見的誤解就是認為: ng是定時輪詢去檢查model是否變更。
其實,ng只有在指定事件觸發后,才進入$digest cycle:
- DOM事件,譬如用戶輸入文本,點擊按鈕等。(ng-click)
- XHR響應事件 ($http)
- 瀏覽器Location變更事件 ($location)
- Timer事件($timeout, $interval)
- 執行$digest()或$apply()
$digest后批量更新UI參考《mastering web application development with angularjs》 P294
傳統的JS MVC框架, 數據變更是通過setter去觸發事件,然后立即更新UI。
而angular則是進入$digest cycle,等待所有model都穩定后,才批量一次性更新UI。
這種機制能減少瀏覽器repaint次數,從而提高性能。
提速 $digest cycle 關鍵點參考《mastering web application development with angularjs》 P296
另, 推薦閱讀: 構建自己的AngularJS,第一部分:Scope和Digest
盡少的觸發$digest (P310)
盡快的執行$digest
優化$watch$scope.$watch(watchExpression, modelChangeCallback), watchExpression可以是String或Function。
避免watchExpression中執行耗時操作,因為它在每次$digest都會執行1~2次。
避免watchExpression中操作dom,因為它很耗時。
console.log也很耗時,記得發布時干掉它。(用grunt groundskeeper)
ng-if vs ng-show, 前者會移除DOM和對應的watch
及時移除不必要的$watch。(angular自動生成的可以通過下文介紹的bindonce)
> 參考《mastering web application development with angularjs》 P303~309
var unwatch = $scope.$watch("someKey", function(newValue, oldValue){ //do sth... if(someCondition){ //當不需要的時候,及時移除watch unwatch(); } });
避免深度watch, 即第三個參數為true
參考《mastering web application development with angularjs》 P313
減少watch的變量長度
如下,angular不會僅對{{variable}}建立watcher,而是對整個p標簽。
雙括號應該被span包裹,因為watch的是外部element
參考《mastering web application development with angularjs》 P314
$apply vs $digestplain text other {{variable}} plain text other
//改為:plain text other plain text other
//或plain text other {{variable}} plain text other
$apply會使ng進入$digest cycle, 并從$rootScope開始遍歷(深度優先)檢查數據變更。
$digest僅會檢查該scope和它的子scope,當你確定當前操作僅影響它們時,用$digest可以稍微提升性能。
> 參考《mastering web application development with angularjs》 P308
一些不必要的操作,放到$timeout里面延遲執行。
如果不涉及數據變更,還可以加上第三個參數false,避免調用$apply。
對時間有要求的,第二個參數可以設置為0。
$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
http://stackoverflow.com/questions/17301572/angularjs-evalasync-vs-timeout
directive中執行的$evalAsync, 會在angular操作DOM之后,瀏覽器渲染之前執行。
controller中執行的$evalAsync, 會在angular操作DOM之前執行,一般不這么用。
而使用$timeout,會在瀏覽器渲染之后執行。
優化ng-repeat 限制列表個數列表對象的數據轉換,在放入scope之前處理。如$scope.dataList = convert(dataFromServer)
可以使用ngInfiniteScroll來做無限滾動。
使用 track by刷新數據時,我們常這么做:$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開始支持內建單次綁定, {{::foo}}
設計文檔: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); });慎用事件
減少事件廣播,使用雙向數據綁定或共享service等方法來代替。
$broadcast會遍歷scope和它的子scope,而不是只通知注冊了該事件的子scope。
一個優化方式是使用$emit, 參見https://github.com/angular/angular.js/issues/4574
1.2.7版本對事件做過一個優化,參見https://github.com/angular/angular.js/blob/master/CHANGELOG.md#127-emoji-clairvoyance-2014-01-03
對高頻的事件做緩沖限速,避免觸發太頻繁。
directive跟scope數據無關的操作放在compile階段,它只執行一次。
除了directive外其他地方,特別是controller里面不要操作dom, 尤其是綁定到scope后,便是災難。
改變以前使用JQuery那樣以DOM為中心的思維,擁抱以數據為中心的思維。參見
> 參見: http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background
> 翻譯: http://blog.jobbole.com/46589/
AngularJS Batarang是官方提供的chrome插件
搬運自: http://atian25.github.io/2014/05/09/angular-performace/
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78079.html
摘要:在理想的情況下,我們甚至可以立即將應用程序升級到。于是,在中,我們可以得到些什么正如我們所看到的,的新增特性除之外并不是很亮眼,盡管這些特性非常好用,但對于大多數應用程序來說并不重要。 轉載請注明出處:葡萄城官網,葡萄城為開發者提供專業的開發工具、解決方案和服務,賦能開發者。 本文由葡萄城翻譯并發布 showImg(https://segmentfault.com/img/bVbrk...
摘要:前端日報精選騰訊前端團隊社區源碼分析入門指南一些關于使用的心得基本類型與引用類型知多少掘金中文第期框架選型周刊第期入門系列模塊車棧重構基于的網絡請求庫某熊的全棧之路的那些奇技淫巧的平凡之路模仿寫個數組監聽掘 2017-07-01 前端日報 精選 Why you shouldn`t use Preact, Fast-React, etc. to replace React today -...
摘要:但是在第一次上線后,發現自己的網頁打開后,加載的速度需要秒,當時第一感覺就是,我是不是應該換框架最終在網絡上摸索出來一系列的解決方案,得到了現在只要秒就可以完成加載任務這一系列的解決方案我會在整理好后再告訴大家。 火星積雪 摘要:火星積雪 這個是目前正在開發的一個項目,主要目的是為了提供一個快捷的集成應用的,這么一個小應用中心! 項目框架 angular5 angular-cli ...
閱讀 2570·2021-11-23 09:51
閱讀 3120·2019-08-30 15:54
閱讀 1071·2019-08-30 14:14
閱讀 3542·2019-08-30 13:59
閱讀 1393·2019-08-29 17:09
閱讀 1468·2019-08-29 16:24
閱讀 2848·2019-08-29 15:43
閱讀 911·2019-08-29 12:45