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