首頁 web前端 js教程 angular如何進行效能優化?變更檢測方式淺析

angular如何進行效能優化?變更檢測方式淺析

Jul 06, 2022 pm 08:09 PM
angular.js

angular如何進行效能最佳化?以下這篇文章給大家深入介紹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 面板,如下圖所示:

angular如何進行效能優化?變更檢測方式淺析

#透過觀察FPS 面板,如下圖所示:

angular如何進行效能優化?變更檢測方式淺析

#透過觀察FPS 面板,如下圖所示:

#dFPS 面板面板, ,我們可以很方便的對目前頁面的流暢度進行監控

1 影響頁面效能的因素angular如何進行效能優化?變更檢測方式淺析

         頁面互動是否流暢,且在於頁面回應是否流暢,而頁面回應本質上是將頁面狀態的變更重新渲染到頁面上的過程。

         頁面回應過程大致如下:

一般情況Event Handler事件處理邏輯不會消耗太多時間,所以影響angular效能的因素主要在於非同步事件觸發

變更偵測

。 一般情況Event Handler事件處理邏輯不會消耗太多時間,所以影響angular效能的因素主要在於非同步事件觸發和變更偵測。

         對angular來說,頁面渲染的過程就是變更偵測的過程,可以理解為angular的變更偵測要在16.6ms內完成才不會導致頁面遺失畫面、卡頓。 可以從以下三個方面優化頁面回應的效能。 (1)對於觸發事件階段,可以

減少非同步事件的觸發

,來減少整體的變更偵測次數和重新渲染;

(2)對於Event Handler 執行邏輯階段,可以透過最佳化複雜程式碼邏輯來減少執行時間;(3)對於Change Detection 偵測資料綁定並更新DOM 階段,可以減少變更偵測模板資料的計算次數來減少渲染時間;

#對於(2)Event Handler要具體問題具體分析,不做討論,主要針對( 1)(3)進行最佳化

2

最佳化方案

angular如何進行效能優化?變更檢測方式淺析

2.1 減少非同步事件觸發

         Angular在預設變更偵測模式下,非同步事件會觸發全域的變更偵測,因此,減少非同步事件的觸發會大幅提升angular的效能。

         非同步事件包含Macro Task(巨集任務)事件與Micro Task微任務事件

         對非同步事件的最佳化事件為最佳化事件的最佳化事件。例如document上的click、mouseup、mousemove…等監聽事件。

###         監聽事件情境:######                Renderer2.listen( ####                document.addEventListener(…)## ####         dom監聽事件,且不需要觸發的時候一定要移除。 ###

範例:[pop]提示框指令

         使用情境:表格列篩選,點選圖示以外的地方,或是頁面捲動,列篩選彈框隱藏

         先前的做法是指

   在pop指令裡監聽document的click事件和scroll事件,這樣有個弊端就是提示框未顯示,但依然存在監聽事件,很不合理。

         合理的解決方案:當提示框顯示的時候才去監聽click和scroll事件,隱藏的時候就移除監聽事件。 angular如何進行效能優化?變更檢測方式淺析

對於頻繁觸發的dom監聽事件,可以使用rjx的運算元對事件進行最佳化。詳情請參考Rjx操作符

RxJS Marbles

2.2 變更偵測

什麼是變更偵測?          要瞭解變更偵測,我們可以從變更偵測的目標中找出答案。 angular變更偵測目標,是讓模型(TypeScript程式碼)與範本(HTML)保持同步。因此,變更偵測可以理解為:偵測模型變更的同時,更新範本( DOM

變更偵測流程是什麼? angular如何進行效能優化?變更檢測方式淺析

       透過在元件樹中依照

自頂向下

的順序執行變更偵測,也就是先對父元件執行變更偵測,再對子組件進行變更檢測。首先檢查父元件的資料變更,然後更新父元件模板,在更新模板的時候遇到子元件,會去更新子元件上綁定的值,然後進入子元件,看@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 等建立。
    EventTask,由 addEventListener 等創建,例如dom事件。
  • ZoneSpec對象,創建一個ngZone 時給它提供的參數,有三個可以觸發檢測的鉤子:
    • onInvoke,呼叫某個回調函數時觸發的鉤子。
    • onInvokeTask,ZoneTask 被觸發時觸發的鉤子,例如 setTimeout 到時。
    onHasTask,偵測到有或沒有 ZoneTask 時觸發的鉤子(即對第一個 schedule 的 zone 和最後一個 invoke 或 cancel 的 task 觸發)。
ZoneDelegate類,負責呼叫鉤子。

偵測過程原理大概如下:

       使用者操作觸發非同步事件(例如:dom事件,介面請求…)

=>  ZoneTask類別處理事件。 invokeTask()函數中呼叫zone的runTask()方法,在runTask方法中,zone透過_zoneDelegate實例屬性,呼叫ZoneSpec的鉤子

=>  ZoneSpec的三個鉤子(onInvokeTask、onInvoke、onHasTask)鉤子裡透過checkStable()函數觸發zone.onMicrotaskEmpty.emit(null)通知=>  根元件監聽onMicrotaskEmpty後呼叫tick(),tick方法中呼叫 

detectChanges()

#detect##從從根元件開始偵測=> ··· refreshView()呼叫executeTemplate()executeTemplate方法中呼叫

templateFn ()

更新範本、子元件綁定的值(

這時候會去偵測子元件的###@Input()###輸入引用是否改變,如果有改變,會將子元件標記為###Dirty###,也就是該子元件需要變更偵測###)######詳細變更偵測原理流程圖:###

angular如何進行效能優化?變更檢測方式淺析

簡化流程:

觸發非同步事件

=>  ZoneTask處理事件

=> 觸發非同步事件

=>  ZoneTask處理事件

=> ZoneDelegate 呼叫ZoneSpec的鉤子觸發onMicrotaskEmpty通知angular如何進行效能優化?變更檢測方式淺析

=> 根元件收到onMicrotaskEmpty通知,執行tick(),開始偵測並更新dom

由上述程式碼可知,

當微任務為空的時候才會觸發變更偵測

angular如何進行效能優化?變更檢測方式淺析

簡略變更偵測原理流程圖:

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()鉤子來手動觸發目前元件的變更偵測。

angular如何進行效能優化?變更檢測方式淺析範例:app-icon-react動態圖示元件

2.2.3 除錯方法

1angular如何進行效能優化?變更檢測方式淺析         方式1:可在瀏覽器控制台,使用Angular DevTools外掛檢視某次dom事件,angular的偵測狀況:

         方式2:可在控制台直接輸入:ng.profiler.timeChangeDetection()檢視檢測時間,這種方式可查看全域的檢測時間。參考部落格

Profiling Angular Change Detection1angular如何進行效能優化?變更檢測方式淺析

2.3 範本(HTML)最佳化

2.3.1 減少DOM渲染:ngFor加trackBy

         使用*ngFor 的trackBy 屬性,Angular 只變更並重新渲染已變更的條目,而不必重新載入整個條目清單。

         例如:表格排序場景。 ngFor如果加了trackBy,表格渲染的時候只會移動行dom元素,如果不加trackBy,會先刪除現有的表格dom元素,再新增行dom元素。顯然只移動dom元素效能會好很多。

2.3.2 模板表達式中不要使用函數

         不要在Angular 模板表達式中使用函數調用,可以用管道pipe代替,也可以手動計算後用一個變數代替。模板中使用函數,不管值有沒有改變,每次變更偵測的時候都會執行函數,都會影響效能。 ######         範本中使用函數的情境:###

1angular如何進行效能優化?變更檢測方式淺析

2.3.3 減少ngFor的使用

使用ngFor,資料量大的時候會影響效能。

範例:

使用ngFor:

1angular如何進行效能優化?變更檢測方式淺析

1angular如何進行效能優化?變更檢測方式淺析

#不使用ngFor:效能提升10倍左右

1angular如何進行效能優化?變更檢測方式淺析

1angular如何進行效能優化?變更檢測方式淺析

更多程式相關知識,請造訪:程式設計影片! !

以上是angular如何進行效能優化?變更檢測方式淺析的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

Angular學習之聊聊獨立組件(Standalone Component) Angular學習之聊聊獨立組件(Standalone Component) Dec 19, 2022 pm 07:24 PM

這篇文章帶大家繼續angular的學習,簡單了解一下Angular中的獨立組件(Standalone Component),希望對大家有幫助!

angular學習之詳解狀態管理器NgRx angular學習之詳解狀態管理器NgRx May 25, 2022 am 11:01 AM

這篇文章帶大家深入了解angular的狀態管理器NgRx,介紹一下NgRx的使用方法,希望對大家有幫助!

淺析Angular中的獨立組件,看看怎麼使用 淺析Angular中的獨立組件,看看怎麼使用 Jun 23, 2022 pm 03:49 PM

這篇文章帶大家了解Angular中的獨立元件,看看怎麼在Angular中建立一個獨立元件,怎麼在獨立元件中導入已有的模組,希望對大家有幫助!

專案過大怎麼辦?如何合理拆分Angular項目? 專案過大怎麼辦?如何合理拆分Angular項目? Jul 26, 2022 pm 07:18 PM

Angular專案過大,怎麼合理拆分它?以下這篇文章跟大家介紹一下合理分割Angular專案的方法,希望對大家有幫助!

聊聊自訂angular-datetime-picker格式的方法 聊聊自訂angular-datetime-picker格式的方法 Sep 08, 2022 pm 08:29 PM

怎麼自訂angular-datetime-picker格式?以下這篇文章聊聊自訂格式的方法,希望對大家有幫助!

手把手帶你了解Angular中的依賴注入 手把手帶你了解Angular中的依賴注入 Dec 02, 2022 pm 09:14 PM

這篇文章帶大家了解一下依賴注入,介紹一下依賴注入解決的問題和它原生的寫法是什麼,並聊聊Angular的依賴注入框架,希望對大家有所幫助!

深入了解Angular中的NgModule(模組) 深入了解Angular中的NgModule(模組) Sep 05, 2022 pm 07:07 PM

NgModule 模組是Angular種一個重要的點,因為Angular的基本構造塊就是NgModule。這篇文章就來帶大家了解Angular中的NgModule模組,希望對大家有幫助!

淺析IDEA中如何開發Angular 淺析IDEA中如何開發Angular Jun 01, 2022 am 11:23 AM

這篇文章帶大家了解如何使用IDEA開發Angular,簡單介紹一下JetBrains IDEA中新建專案、運行專案的方法,希望對大家有幫助!

See all articles