angular如何進行效能最佳化?以下這篇文章給大家深入介紹angular 效能優化方案--變更偵測,希望對大家有幫助!
angular 效能最佳化-變更偵測
前端效能指標描述,業界皆各有說詞,總結下來都和首屏表現和頁面流暢度相關, 本次將會從頁面流暢度的角度,對頁面互動效能優化進行分析。 【相關教學推薦:《angular教學》】
什麼是頁面流暢度?
頁面流暢度是透過幀率FPS(Frames Per Second - 每秒傳輸幀數)判定的,一般主流的瀏覽器螢幕更新率都在60Hz(每秒刷新60次),最優的幀率在60 FPS,幀率越高,頁面就越流暢,60Hz意味著每隔16.6ms會刷新一次顯示屏,也就是每一次渲染頁面需要在16.6ms內完成,否則就會導致頁面失幀,出現卡頓現象。 根因在於:瀏覽器中的 JavaScript 執行和頁面渲染會互相阻塞
。
在Chrome 的devtools 中我們可以執行Cmd Shift P 輸入show fps 快速開啟fps 面板,如下圖所示:
#透過觀察FPS 面板,如下圖所示:
#透過觀察FPS 面板,如下圖所示:
#dFPS 面板面板, ,我們可以很方便的對目前頁面的流暢度進行監控
1 影響頁面效能的因素
頁面互動是否流暢,且在於頁面回應是否流暢,而
頁面回應本質上是將頁面狀態的變更重新渲染到頁面上的過程。
一般情況Event Handler事件處理邏輯不會消耗太多時間,所以影響angular效能的因素主要在於非同步事件觸發和
變更偵測。 一般情況Event Handler事件處理邏輯不會消耗太多時間,所以影響angular效能的因素主要在於非同步事件觸發和變更偵測。
對angular來說,頁面渲染的過程就是變更偵測的過程,可以理解為angular的變更偵測要在16.6ms內完成才不會導致頁面遺失畫面、卡頓。 可以從以下三個方面優化頁面回應的效能。 (1)對於觸發事件階段,可以
減少非同步事件的觸發,來減少整體的變更偵測次數和重新渲染;
(2)對於Event Handler 執行邏輯階段,可以透過最佳化複雜程式碼邏輯來減少執行時間;(3)對於Change Detection 偵測資料綁定並更新DOM 階段,可以減少變更偵測和模板資料的計算次數來減少渲染時間;
#對於(2)Event Handler要具體問題具體分析,不做討論,主要針對( 1)(3)進行最佳化
2
最佳化方案
2.1 減少非同步事件觸發
Angular在預設變更偵測模式下,非同步事件會觸發全域的變更偵測,因此,減少非同步事件的觸發會大幅提升angular的效能。 非同步事件包含Macro Task(巨集任務)事件與Micro Task微任務事件對非同步事件的最佳化事件為最佳化事件的最佳化事件。例如document上的click、mouseup、mousemove…等監聽事件。
### 監聽事件情境:###### Renderer2.listen( #### document.addEventListener(…)## #### dom監聽事件,且不需要觸發的時候一定要移除。 ###範例:[pop]提示框指令
使用情境:表格列篩選,點選圖示以外的地方,或是頁面捲動,列篩選彈框隱藏
先前的做法是指
在pop指令裡監聽document的click事件和scroll事件,這樣有個弊端就是提示框未顯示,但依然存在監聽事件,很不合理。
合理的解決方案:當提示框顯示的時候才去監聽click和scroll事件,隱藏的時候就移除監聽事件。
對於頻繁觸發的dom監聽事件,可以使用rjx的運算元對事件進行最佳化。詳情請參考Rjx操作符。
RxJS Marbles。
2.2 變更偵測什麼是變更偵測? 要瞭解變更偵測,我們可以從變更偵測的目標中找出答案。 angular變更偵測目標,是讓模型(TypeScript程式碼)與範本(HTML)保持同步。因此,變更偵測可以理解為:偵測模型變更的同時,更新範本( DOM )
。變更偵測流程是什麼?
透過在元件樹中依照
自頂向下的順序執行變更偵測,也就是先對父元件執行變更偵測,再對子組件進行變更檢測。首先檢查父元件的資料變更,然後更新父元件模板,在更新模板的時候遇到子元件,會去更新子元件上綁定的值,然後進入子元件,看@Input輸入值的索引是否改變,如果改變就將該子元件標記為dirty,也就是後續需要變更偵測的,標記完子元件之後,繼續更新父元件中子元件後面的模板,父元件模板全部更新完之後再去對子元件做變更檢測。
2.2.1 angular變更偵測原理
在預設變更偵測default模式下,非同步事件觸發Angular的變更偵測的原理是angular透過使用Zone.js處理非同步事件時呼叫了ApplicationRef的tick()方法從根組件到子組件執行變更檢測。 Angular 應用初始化過程中,實例化了一個zone (NgZone),然後將所有邏輯都跑在該物件的 _inner 物件中。
- Zone.js實作了以下幾個類別:
- Zone類,JavaScript 事件的執行環境,和執行緒一樣,它們可以帶一些數據,並且可能擁有父子 zone。
- ZoneTask類,包裝後的非同步事件,這些 task 有三種子類:
- MicroTask,由 Promise 創建。
- MacroTask,由 setTimeout 等建立。
- ZoneSpec對象,創建一個ngZone 時給它提供的參數,有三個可以觸發檢測的鉤子:
- onInvoke,呼叫某個回調函數時觸發的鉤子。
- onInvokeTask,ZoneTask 被觸發時觸發的鉤子,例如 setTimeout 到時。
偵測過程原理大概如下:
使用者操作觸發非同步事件(例如:dom事件,介面請求…)
=> ZoneTask類別處理事件。 invokeTask()函數中呼叫zone的runTask()方法,在runTask方法中,zone透過_zoneDelegate實例屬性,呼叫ZoneSpec的鉤子
=> ZoneSpec的三個鉤子(onInvokeTask、onInvoke、onHasTask)鉤子裡透過checkStable()函數觸發zone.onMicrotaskEmpty.emit(null)通知=> 根元件監聽onMicrotaskEmpty後呼叫tick(),tick方法中呼叫
#detect
##從從根元件開始偵測
=> ···
refreshView()
呼叫executeTemplate()
,executeTemplate
方法中呼叫
更新範本、子元件綁定的值(
這時候會去偵測子元件的###@Input()###輸入引用是否改變,如果有改變,會將子元件標記為###Dirty###,也就是該子元件需要變更偵測###)######詳細變更偵測原理流程圖:###簡化流程:
觸發非同步事件
=> ZoneTask處理事件
=> 觸發非同步事件
=> ZoneTask處理事件
=> ZoneDelegate 呼叫ZoneSpec的鉤子觸發onMicrotaskEmpty通知
由上述程式碼可知,
當微任務為空的時候才會觸發變更偵測。
Angular 原始碼解析 Zone.js參考
blog#。
2.2.2 變更偵測最佳化方案
1 )使用OnPush 模式
原理:減少1次變更偵測的耗時。
OnPush模式與Default模式的差異在於:dom監聽事件、timer事件、promise都不會觸發變更偵測。 Default模式的元件狀態始終為CheckAlways,表示元件每次偵測週期都要偵測。
OnPush模式下:以下情況會觸發變更偵測
S1、元件的@Input引用變更。
S2、元件的DOM所綁定的事件,包含它子元件的DOM所綁定的事件,如 click、submit、mouse down。 @HostListener()
注意:
以renderer2.listen()監聽的dom事件不會觸發變更偵測
Event List 會觸發變更偵測
S3、Observable 訂閱事件,同時設定Async pipe。
S4、使用以下方式手動觸發變更偵測:
ChangeDetectorRef.detectChanges():觸發目前元件和非OnPush子元件的變更偵測。
ChangeDetectorRef.markForCheck():將目前視圖及其所有的祖先標記為髒,下次偵測週期時會觸發偵測。
ApplicationRef.tick():不會觸發變更偵測
2 )使用NgZone.runOutsideAngular()
原則:減少變更偵測次數
# 全域dom事件監聽寫在NgZone.runOutsideAngular()方法的回呼裡面,dom事件將不會觸發angular的變更偵測。如果目前元件未更新,可以在回呼函數裡執行ChangeDetectorRef的detectChanges()鉤子來手動觸發目前元件的變更偵測。範例:app-icon-react動態圖示元件
方式1:可在瀏覽器控制台,使用Angular DevTools外掛檢視某次dom事件,angular的偵測狀況:
Profiling Angular Change Detection
2.3 範本(HTML)最佳化
2.3.1 減少DOM渲染:ngFor加trackBy 使用*ngFor 的trackBy 屬性,Angular 只變更並重新渲染已變更的條目,而不必重新載入整個條目清單。 例如:表格排序場景。 ngFor如果加了trackBy,表格渲染的時候只會移動行dom元素,如果不加trackBy,會先刪除現有的表格dom元素,再新增行dom元素。顯然只移動dom元素效能會好很多。 2.3.2 模板表達式中不要使用函數 不要在Angular 模板表達式中使用函數調用,可以用管道pipe代替,也可以手動計算後用一個變數代替。模板中使用函數,不管值有沒有改變,每次變更偵測的時候都會執行函數,都會影響效能。 ###### 範本中使用函數的情境:###2.3.3 減少ngFor的使用
使用ngFor,資料量大的時候會影響效能。
範例:
使用ngFor:
#不使用ngFor:效能提升10倍左右
更多程式相關知識,請造訪:程式設計影片! !
以上是angular如何進行效能優化?變更檢測方式淺析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本篇文章带大家继续angular的学习,简单了解一下Angular中的独立组件(Standalone Component),希望对大家有所帮助!

本篇文章带大家深入了解一下angular的状态管理器NgRx,介绍一下NgRx的使用方法,希望对大家有所帮助!

Angular项目过大,怎么合理拆分它?下面本篇文章给大家介绍一下合理拆分Angular项目的方法,希望对大家有所帮助!

怎么自定义angular-datetime-picker格式?下面本篇文章聊聊自定义格式的方法,希望对大家有所帮助!

本篇文章带大家了解一下Angular中的独立组件,看看怎么在Angular中创建一个独立组件,怎么在独立组件中导入已有的模块,希望对大家有所帮助!

本篇文章带大家了解一下依赖注入,介绍一下依赖注入解决的问题和它原生的写法是什么,并聊聊Angular的依赖注入框架,希望对大家有所帮助!

本篇文章带大家深入了解一下angular中的几个特殊选择器:host、:host-context、::ng-deep,希望对大家有所帮助!

NgModule 模块是Angular种一个重要的点,因为Angular的基本构造块就是NgModule。本篇文章就来带大家了解一下Angular中的NgModule模块,希望对大家有所帮助!


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

禪工作室 13.0.1
強大的PHP整合開發環境

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具