什麼是變更檢測?以下這篇文章帶大家聊聊Angular中的變更偵測機制,介紹一下狀態變化如何通知變更偵測、Angular變更偵測策略,希望對大家有幫助。
概括: 一種更改检测机制
,用於遍歷元件樹,檢查每個元件的變化,並在元件屬性改變的時候觸發DOM
的更新。 【相關教學推薦:《angular教學》】
變更偵測的基本任務: 取得程式的內部状态
並使之在使用者介面可见
。這個狀態可以是任何的物件、陣列、基本資料型別。
事件驅動,來源有以下三大類:
事件:頁面click、submit、mouse down…
XHR:從後端伺服器拿到數據
Timers:setTimeout()、setInterval()
這幾點有一個共同點,就是它們都是非同步的,也就是說,所有的异步操作
是可能導致資料變化的根源因素,所以每當執行一些非同步操作時,我們的應用程式狀態可能會改變,而這時則需要去更新視圖
在Angular
當中則接入了NgZone
,由它來監聽Angular所有的异步事件
,Angular 在啟動時會重寫(透過Zone.js
)部分底層瀏覽器API(暴力的攔截了所有的非同步事件)。
常見的有兩種方式來觸發變化檢測,一種方法是基於組件的生命週期鉤子
ngAfterViewChecked() { console.log('cluster-master.component cd'); }
另一種方法是手動控制變更偵測的開啟或關閉,並手動觸發
constructor(private cd: ChangeDetectorRef) { cd.detach() setInterval(() => { this.cd.detectChanges() }, 5000) }
Angular 的核心是組件化,組件的嵌套會使得最終形成一棵组件树
,Angular 的變化檢測可以分組件進行,每個組件都有對應的变化检测器ChangeDetector
,可想而知這些變化檢測器也會構成一棵樹。
在Angular 中每個元件都有自己的變化偵測器,這使得我們可以對每個元件分別控制如何以及何時進行變更偵測。
Angular也讓開發者擁有客製化變化偵測策略的能力。
default:每次
變更偵測都會造成元件的變更偵測,包括其他组件
的狀態變化,以及本组件
引用型變數內部屬性值變化
Onpush: 每次變更偵測會跳過本元件的變更檢查,除非满足一些条件
4.1 default
Angular 預設的變化偵測機制是ChangeDetectionStrategy.Default
,每次非同步事件callback 結束後,NgZone會觸發整个组件树
至上而下
做變化偵測
4.2 onPush
OnPush 策略,用以跳过
某個component 以及它下面所有子组件
的變化來偵測
其實在設定了OnPush
策略以後,還是有許多方法可以觸發變更偵測的;
1)組件的@Input
屬性的引用
發生變化。
2)元件內的DOM
事件,包括它子元件的DOM 事件,如click、submit、mouse down
。
3)元件內的Observable
訂閱事件,同時設定Async pipe
。
4)元件內手動使用ChangeDetectorRef.detectChanges()、ChangeDetectorRef.markForCheck()、ApplicationRef.tick()
方法
markForCheck():使用於子组件
,该子组件到根组件
之間的路徑標記起來,通知angular 偵測器下次變更偵測時一定
檢查此路徑上的元件,即使設定了變更偵測策略為onPush
detectChanges():手動啟動该组件到各个子组件
的變更偵測
detach():將組件的偵測器從偵測器數中脱离
,不再受偵測機制的控制,除非重新attach 上
reattach():把脫離的偵測器重新链接
到偵測器樹上