摘要:別著急,的開發團隊已經考慮到了這個問題,上述的檢測機制只是一種默認的檢測機制,還提供一種的檢測機制設置元數據屬性。
什么是變化監測
在使用 Angular 進行開發中,我們常用到 Angular 中的綁定——模型到視圖的輸入綁定、視圖到模型的輸出綁定以及視圖與模型的雙向綁定。而這些綁定的值之所以能在視圖與模型之間保持同步,正是得益于Angular中的變化檢測。
簡單來說,變化檢測就是 Angular 用來檢測視圖與模型之間綁定的值是否發生了改變,當檢測到模型中綁定的值發生改變時,則同步到視圖上,反之,當檢測到視圖上綁定的值發生改變時,則回調對應的綁定函數。
變化監測的源頭變化監測的關鍵在于如何最小粒度地監測到綁定的值是否發生了改變,那么在什么情況下會導致這些綁定的值發生變化呢?我們可以看一下我們常用的幾種場景:
Events: click/hover/...@Component({ selector: "demo-component", template: `{{name}}
` }) export class DemoComponent { name: string = "Tom"; changeName() { this.name = "Jerry"; } }
我們在模板中通過插值表達式綁定了 name 屬性。當點擊change name按鈕時,改變了 name 屬性的值,這時模板視圖顯示內容也發生了改變。
XHR/webSocket@Component({ selector: "demo-component", template: `{{name}}
` }) export class DemoComponent implements OnInit { name: string = "Tom"; constructor(public http: HttpClient) {} ngOnInit() { // 假設有這個./getNewName請求,返回一個新值"Jerry" this.http.get("./getNewName").subscribe((data: string) => { this.name = data; }); } }
我們在這個組件的 ngOnInit 函數里向服務器端發送了一個 Ajax 請求,當這個請求返回結果時,同樣會改變當前模板視圖上綁定的 name 屬性的值。
Times: setTimeout/requestAnimationFrame@Component({ selector: "demo-component", template: `{{name}}
` }) export class DemoComponent implements OnInit { name: string = "Tom"; constructor() {} ngOnInit() { // 假設有這個./getNewName請求,返回一個新值"Jerry" setTimeout(() => { this.name = "Jerry"; }, 1000); } }
我們在這個組件的ngOnInit函數里通過設定一個定時任務,當定時任務執行時,同樣會改變當前視圖上綁定的name屬性的值。
總結其實,我們不難發現上述三種情況都有一個共同點,即這些導致綁定值發生改變的事件都是異步發生的。
Angular并不是捕捉對象的變動,它采用的是在適當的時機去檢驗對象的值是否被改動,這個時機就是這些異步事件的發生。
這個時機是由 NgZone 這個服務去掌控的,它獲取到了整個應用的執行上下文,能夠對相關的異步事件發生、完成或者異常等進行捕獲,然后驅動 Angular 的變化監測機制執行。
變化監測的處理機制通過上面的介紹,我們大致明白了變化檢測是如何被觸發的,那么 Angular 中的變化監測是如何執行的呢?
首先我們需要知道的是,對于每一個組件,都有一個對應的變化監測器;即每一個 Component 都對應有一個changeDetector,我們可以在 Component 中通過依賴注入來獲取到changeDetector。
而我們的多個 Component 是一個樹狀結構的組織,由于一個 Component 對應一個changeDetector,那么changeDetector之間同樣是一個樹狀結構的組織。
最后我們需要記住的一點是,每次變化監測都是從 Component 樹根開始的。
舉個例子子組件:
@Component({ selector: "demo-child", template: `{{title}}
{{paramOne}}
{{paramTwo}}
` }) export class DemoChildComponent { title: string = "子組件標題"; @Input() paramOne: any; // 輸入屬性1 @Input() paramTwo: any; // 輸入屬性2 }
父組件:
@Component({ selector: "demo-parent", template: `{{title}}
` }) export class DemoParentComponent { title: string = "父組件標題"; paramOneVal: any = "傳遞給paramOne的數據"; paramTwoVal: any = "傳遞給paramTwo的數據"; changeVal() { this.paramOneVal = "改變之后的傳遞給paramOne的數據"; } }
上面的代碼中,DemoParentComponent 通過
當我們點擊 DemoParentComponent 的 button 時,會回調到 changeVal 方法,然后會觸發變化監測的執行,變化監測流程如下:
首先變化檢測從 DemoParentComponent 開始:
檢測 title 值是否發生了變化:沒有發生變化
檢測 paramOneVal 值是否發生了變化:發生了變化(點擊按鈕調用changeVal()方法改變的)
檢測 paramTwoVal 值是否發生了變化:沒有發生變化
然后變化檢測進入到葉子節點 DemoChildComponent:
檢測 title 值是否發生了改變:沒有發生變化
檢測 paramOne 是否發生了變化:發生了改變(由于父組件的屬性paramOneVal發生了改變)
檢測 paramTwo 是否發生了改變:沒有發生變化
最后,因為 DemoChildComponent 再也沒有了葉子節點,所以變化監測將更新DOM,同步視圖與模型之間的變化。
變化監測策略學習了變化監測的處理機制之后,你可能會想,這機制未免也有點太簡單粗暴了吧,假如我的應用中有成百上千個 Component,隨便一個 Component 觸發了監測,那么都需要從根節點到葉子節點重新檢測一遍。
別著急,Angular 的開發團隊已經考慮到了這個問題,上述的檢測機制只是一種默認的檢測機制,Angular 還提供一種 OnPush 的檢測機制(設置元數據屬性 changeDetection: ChangeDetectionStrategy.OnPush)。
OnPush 與 Default 之間的差別:當檢測到與子組件輸入綁定的值沒有發生改變時,變化檢測就不會深入到子組件中去。
變化監測類 - ChangeDetectorRef上面說到我們可以修改組件元數據屬性 changeDetection 來修改組件的變化監測策略(ChangeDetectionStrategy.Default 或 ChangeDetectionStrategy.OnPush),除了這個,我們還可以使用 ChangeDetectorRef 來更加靈活的控制組件的變化監測。
Angular 在整個運行期間都會為每一個組件創建 ChangeDetectorRef 的實例,該實例提供了相關方法來手動管理變化監測。有了這個類,我們自己就可以自定義組件的變化監測策略了,如停止/啟用變化監測或者按指定路徑變化監測等等。
相關方法如下:
markForCheck():把根組件到該組件之間的這條路徑標記起來,通知Angular在下次觸發變化監測時必須檢查這條路徑上的組件。
detach():從變化監測樹中分離變化監測器,該組件的變化監測器將不再執行變化監測,除非再次手動執行reattach()方法。
reattach():把分離的變化監測器重新安裝上,使得該組件及其子組件都能執行變化監測。
detectChanges():手動觸發執行該組件到各個子組件的一次變化監測。
使用方法也很簡單,直接在組件中注入即可:
@Component({ selector: "demo-parent", template: `{{title}}
` }) export class DemoParentComponent implements OnInit { title: string = "組件標題"; constructor(public cdRef: ChangeDetectorRef) {} ngOnInit() { this.cdRef.detach(); // 停止組件的變化監測,看需求使用不同的方法 } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93778.html
摘要:組件元數據組件元數據等,下文將著重講解每個元數據的含義。建議此時獲取數據,不要在構造函數中獲取。每次變化監測發生時被調用。銷毀指令組件之前觸發。 Web Component 在介紹Angular Component之前,我們先簡單了解下W3C Web Components 定義 W3C為統一組件化標準方式,提出Web Component的標準。 每個組件包含自己的html、css、j...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:更多資源請文章轉自月份前端資源分享的作用數組元素隨機化排序算法實現學習筆記數組隨機排序個變態題解析上個變態題解析下中的數字前端開發筆記本過目不忘正則表達式聊一聊前端存儲那些事兒一鍵分享到各種寫給剛入門的前端工程師的前后端交互指南物聯網世界的 更多資源請Star:https://github.com/maidishike... 文章轉自:https://github.com/jsfr...
閱讀 1314·2019-08-30 15:44
閱讀 1983·2019-08-30 13:49
閱讀 1659·2019-08-26 13:54
閱讀 3492·2019-08-26 10:20
閱讀 3256·2019-08-23 17:18
閱讀 3299·2019-08-23 17:05
閱讀 2135·2019-08-23 15:38
閱讀 1018·2019-08-23 14:35