本篇內(nèi)容介紹了“Angular變更檢測機制怎么進行性能優(yōu)化”的有關知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!
成都創(chuàng)新互聯(lián)始終堅持【策劃先行,效果至上】的經(jīng)營理念,通過多達十多年累計超上千家客戶的網(wǎng)站建設總結(jié)了一套系統(tǒng)有效的網(wǎng)絡營銷推廣解決方案,現(xiàn)已廣泛運用于各行各業(yè)的客戶,其中包括:VR全景等企業(yè),備受客戶贊揚。
組件內(nèi)的數(shù)據(jù)狀態(tài)變化以后,需要對應更新視圖。這種將視圖和數(shù)據(jù)同步的機制,就叫變化檢測。
只要發(fā)生了異步操作(Events, Timer, XHR),Angular 就會認為有狀態(tài)可能發(fā)生變化了,然后就會進行變更檢測。
Events::click,mouseover,mouseout,keyup,keydown 等瀏覽器事件;
Timer:setTimeout/setInterval;
XHR:各類請求等。
既然都是對異步操作進行變更檢測,那么Angular是如何訂閱異步請求,進行變更檢測的呢?
這里介紹下NgZone
以及它的fork對象Zone.js
。
Zone.js
用于封裝和攔截瀏覽器中的異步活動、它還提供 異步生命周期的鉤子和 統(tǒng)一的異步錯誤處理機制。
Zone.js
是通過 Monkey Patching(猴子補?。?/em> 的方式來對瀏覽器中的常見方法和元素進行攔截,例如 setTimeout
和 HTMLElement.prototype.onclick
。Angular 在啟動時會利用 Zone.js
修補幾個低級瀏覽器 API,從而實現(xiàn)異步事件的捕獲,并在捕獲時間后調(diào)用變更檢測。
Angular通過forkZone.js
并拓展出一個自己的區(qū)域NgZone
,讓應用中的所有異步操作都會運行在這個區(qū)域中。
Angualr會為每一個組件生成一個變化監(jiān)測器changeDetector
,記錄組件的變化狀態(tài)。
我們在創(chuàng)建了一個Angular 應用后,Angular 會同時創(chuàng)建一個 ApplicationRef
的實例,這個實例代表的就是我們當前創(chuàng)建的這個 Angular 應用的實例。 ApplicationRef
創(chuàng)建的同時,會訂閱 ngZone 中的 onMicrotaskEmpty 事件,在所有的微任務完成后調(diào)用所有的視圖的detectChanges()
來執(zhí)行變更檢測。
更新所有子子組件綁定的屬性
調(diào)用所有子組件生命周期的鉤子 OnChanges, OnInit, DoCheck,AfterContentInit
更新當前組件的DOM
調(diào)用子組件的變更檢測
調(diào)用所有子組件的生命周期鉤子 ngAfterViewInit
舉個栗子,我們在開發(fā)模式的時候可能會遇到這種報錯:
這是由于變更檢測遵循從根組件開始,從上到下,執(zhí)行每個組件的變更檢測,直到最后一個組件達到穩(wěn)定狀態(tài)。而在下一次變更檢測之前,子孫組件都不允許去修改父組件里的屬性。
情況1 在開發(fā)模式下,Angular會進行二次檢測(生產(chǎn)環(huán)境下調(diào)用enableProdMode()
,檢測次數(shù)會降為1)。一旦我們在 第4步 完成后,在子孫組件里修改父組件的屬性,那么,Angular在執(zhí)行第二次檢測的時候,發(fā)現(xiàn)兩次的值不一致,就會出現(xiàn)上述錯誤。
情況2 只要父組件對子組件做了屬性綁定,那么不管是在OnChanges,OnInit,DoCheck,AfterContentInit 和 AfterViewInit 中的任意一個生命周期鉤子中執(zhí)行下述代碼,也會報錯。
// #parent {{data}} <child [data]="data"></child> // in child component ts, execute: this.parent.data = 'new Value';
Default 策略
每次事件觸發(fā)變化檢測(如用戶事件、計時器、XHR、promise 等)時,此默認策略都會從上到下檢查組件樹中的每個組件。這種對組件的依賴關系不做任何假設的保守檢查方式稱為 臟檢查,這種策略在我們應用組件過多時會對我們的應用產(chǎn)生性能的影響。
OnPush 策略
修改組件裝飾器的changeDetection
,設置為 OnPush 策略后,Angular 每次觸發(fā)變化檢測后會跳過該組件和該組件的所以子組件變化檢測。
在 OnPush
策略下,只有以下這幾種情況才會觸發(fā)組件的變化檢測:
detectChanges():它會觸發(fā)當前組件和子組件的變化檢測
markForCheck():它不會觸發(fā)變化檢測,但是會把當前的OnPush組件和所以的父組件為OnPush的組件 標記為需要檢測狀態(tài),在當前或者下一個變化檢測周期進行檢測
ApplicationRef.tick(): 它會根據(jù)組件的變化檢測策略,觸發(fā)整個應用程序的更改檢測
setTimeout()
setInterval()
Promise.resolve().then()
this.http.get('...').subscribe()
輸入值(@Input)更改(入input的值必須是一個新的引用)
當前組件或子組件之一觸發(fā)了事件(但在onPush策略中,以下操作不會觸發(fā)變更檢測)
手動觸發(fā)變更檢測(每個組件都會關聯(lián)一個組件視圖ChangeDetectorRef)
async pipe
由于組件默認執(zhí)行 Default策略 ,任何異步操作都會觸發(fā)整個組件數(shù)從上到下的檢查。即使Angular團隊不斷提升性能,可以在毫秒內(nèi)完成上百次檢測,但是當應用拓展至百上千個組件組成時,龐大的組件樹對應的變更檢測也會達到性能瓶頸。
此時,我們就需要開始分析并減少不必要的檢測次數(shù)。
區(qū)域污染(Zone Pollution)
一般我們在生命周期鉤子里使用第三方庫,比如chart類庫初始化,會自帶requestAnimationRequest/setTimeout/addEventListener,我們可以將初始化方法寫入NgZone
的runOutsideAngular
方法中。
OnPush 策略
對于不涉及更新操作的視圖可以剝離出組件,使用onPush策略,以通知更新的方式刷新視圖(見上方 變更檢測的執(zhí)行策略 部分)。
用 pure pipe 代替 {{function(data)}}
在html文件內(nèi),{{function(data)}}
的寫法會導致每次變更檢測發(fā)生時,所有數(shù)值都會重新被計算。(?:當一個1000條的列表,你只修改了其中一條數(shù)據(jù),但另外另外999條無需更新的數(shù)據(jù)也會被重新運算。)
此時,我們可以使用pipe的方式,只有變更的值會觸發(fā)運算,更新部分視圖。
面對大量數(shù)據(jù)的渲染,選擇虛擬滾動/分頁請求數(shù)據(jù)
以上4點解決方案,來源于Angular團隊的視頻介紹,視頻中以Angular devtool運算次數(shù),來分析問題解決問題。所以,如果你的Angular是9+,請繼續(xù)看下去吧,如何安裝Angular devtool和運行。
Angular 9+, 支持Ivy。
Guide和下載地址
保證運行環(huán)境為開發(fā)環(huán)境
// environment.dev.ts ... production: false ...
angular.json > dev配置項 > "optimization": false
projects > your-project-name > architect > build > configurations > dev > "optimization": false
“Angular變更檢測機制怎么進行性能優(yōu)化”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關的知識可以關注創(chuàng)新互聯(lián)網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!
當前題目:Angular變更檢測機制怎么進行性能優(yōu)化
分享URL:http://jinyejixie.com/article18/gciodp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設計、搜索引擎優(yōu)化、網(wǎng)站設計公司、企業(yè)建站、手機網(wǎng)站建設、關鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)