ngModel源碼淺解
前言
- 以前看過vue的雙向綁定原理,並實現過簡易的demo,可是不多見過有講解angular下,雙向綁定是如何實現的,因此看了下NgModel源碼,發現大同小異,特來講下
- 目前來講只說下ngModel是如何實現的,不涉及屬性綁定及指令方面的知識
- 本篇文章須要知道以下知識才能夠閱讀
自定義表單控件
響應式表單之FormControl
一個ngModel,使用了幾個指令?
- 通常當這麼說,那麼確定意味着使用了不僅一個指令,不然也不會浪費時間說一個肯定的事實
組件也是繼承於指令的,因此這麼說應該也不算錯
-
NgModel
和ControlValueAccessor實現類
,當你要使用NgModel
時,其實是使用了兩個指令
-
NgModel
負責註冊一些函數,全部ControlValueAccessor實現類
實現的4個方法(一個可選禁用方法),最終都是經過NgModel
的來使用的
-
ControlValueAccessor實現類
是規定綁定的內部邏輯,好比何時發送值被變動,當出現值寫入時如何處理
流程示意圖
註冊
- 所謂註冊就是當值變動時.實現類應該用哪些方法去通知已經變動
- 實現類中的
registerOnChange(fn)
,fn就是在註冊階段傳入的,當在這個階段調用實現類.registerOnChange(fn)
,函數被賦值到實現類中,而當值變動時實現類則調用此函數通知值已變動
- 此階段,總共有6個方法被註冊(驗證器分爲同步,異步)
- 實現類中registerOnChange,當視圖中值發生了變動調用傳入函數
- 實現類中registerOnTouched,默認中的實現類是當失去焦點調用傳入函數
- NgModel中FormControl實例中registerOnChange,當值變化是調用傳入函數
- NgModel中FormControl實例中registerOnDisabledChange,禁用狀態變化時,調用實現類中的
setDisabledState
方法
- 驗證器的
registerOnValidatorChange
當驗證器的輸入屬性變化時調用傳入函數
輸入
- 當[ngModel]傳入的值變動後會被
NgModel
的ngOnchanges
鉤子捕獲到
- 若是值變動或爲初始值,那麼會調用鉤子中的
this._updateValue(this.model)
- 此方法會觸發類中
FormControl實例
的值變動
- 當值變動時,上述註冊方法中的3會執行
傳入函數
,函數中會觸發實現類中的writeValue
方法,此時實現類收到了變動值
- 在默認的方法中,收到變動值後,是利用angular的渲染器,寫入到
input
元素的value中
- 輸入流程結束
輸出
- 當
input
或compositionend
事件時,會調用傳入函數onChange
.當blur
事件時,會調用傳入函數onTouched
- 函數收到值後判斷是否是處在更新時機,若是是那麼更新調用
NgModel
中的viewToModelUpdate
- 此方法更新值併發射信號
ngModelChange
告知值已經變動
難點
- 你們應該都知道自定義表單控件怎麼寫,明明沒有寫過
ngModel
input屬性和ngModelChange
output事件,可是卻在實現了ControlValueAccessor
類後神奇的實現了.
- 這裏其實就是由於
NgModel
指令的選擇器是[ngModel]:not([formControlName]):not([formControl])
,也就是說,只要不是響應式表單,那麼全部帶ngModel的都會自動使用這個指令
- 而且該指令在構造時會找他的
ControlValueAccessor實現類
,當找到後,經過將一些變動須要出發的函數告知實現類
而創建了關聯
源碼註釋
疑問
歡迎關注本站公眾號,獲取更多信息