ngModel源碼淺解

前言

  • 以前看過vue的雙向綁定原理,並實現過簡易的demo,可是不多見過有講解angular下,雙向綁定是如何實現的,因此看了下NgModel源碼,發現大同小異,特來講下
  • 目前來講只說下ngModel是如何實現的,不涉及屬性綁定及指令方面的知識
  • 本篇文章須要知道以下知識才能夠閱讀
自定義表單控件
響應式表單之FormControl

一個ngModel,使用了幾個指令?

  • 通常當這麼說,那麼確定意味着使用了不僅一個指令,不然也不會浪費時間說一個肯定的事實
組件也是繼承於指令的,因此這麼說應該也不算錯
  • NgModelControlValueAccessor實現類,當你要使用NgModel時,其實是使用了兩個指令
  • NgModel 負責註冊一些函數,全部ControlValueAccessor實現類實現的4個方法(一個可選禁用方法),最終都是經過NgModel的來使用的
  • ControlValueAccessor實現類是規定綁定的內部邏輯,好比何時發送值被變動,當出現值寫入時如何處理

流程示意圖

圖

註冊

  • 所謂註冊就是當值變動時.實現類應該用哪些方法去通知已經變動
  • 實現類中的registerOnChange(fn),fn就是在註冊階段傳入的,當在這個階段調用實現類.registerOnChange(fn),函數被賦值到實現類中,而當值變動時實現類則調用此函數通知值已變動
  • 此階段,總共有6個方法被註冊(驗證器分爲同步,異步)
  1. 實現類中registerOnChange,當視圖中值發生了變動調用傳入函數
  2. 實現類中registerOnTouched,默認中的實現類是當失去焦點調用傳入函數
  3. NgModel中FormControl實例中registerOnChange,當值變化是調用傳入函數
  4. NgModel中FormControl實例中registerOnDisabledChange,禁用狀態變化時,調用實現類中的setDisabledState方法
  5. 驗證器的registerOnValidatorChange當驗證器的輸入屬性變化時調用傳入函數
  • 傳入函數已經寫在shared.ts文件中

輸入

  • 當[ngModel]傳入的值變動後會被NgModelngOnchanges鉤子捕獲到
  • 若是值變動或爲初始值,那麼會調用鉤子中的this._updateValue(this.model)
  • 此方法會觸發類中FormControl實例的值變動
  • 當值變動時,上述註冊方法中的3會執行傳入函數,函數中會觸發實現類中的writeValue方法,此時實現類收到了變動值
  • 在默認的方法中,收到變動值後,是利用angular的渲染器,寫入到input元素的value中
  • 輸入流程結束

輸出

  • inputcompositionend事件時,會調用傳入函數onChange.當blur事件時,會調用傳入函數onTouched
  • 函數收到值後判斷是否是處在更新時機,若是是那麼更新調用NgModel中的viewToModelUpdate
  • 此方法更新值併發射信號ngModelChange告知值已經變動

難點

  • 你們應該都知道自定義表單控件怎麼寫,明明沒有寫過ngModel input屬性和ngModelChange output事件,可是卻在實現了ControlValueAccessor類後神奇的實現了.
  • 這裏其實就是由於NgModel指令的選擇器是[ngModel]:not([formControlName]):not([formControl]),也就是說,只要不是響應式表單,那麼全部帶ngModel的都會自動使用這個指令
  • 而且該指令在構造時會找他的ControlValueAccessor實現類,當找到後,經過將一些變動須要出發的函數告知實現類而創建了關聯

源碼註釋

  • 在看源碼時也對立面的函數,方法已經相關語句作了註釋,若是你們看上面的仍是感受不太清晰,能夠參照註釋源碼,但願能給予大家幫助
  • ng_model.ts
  • shared.ts
  • default_value_accessor.ts

疑問

  • 若是有哪裏描述的有問題或者不對的請多提寶貴意見
相關文章
相關標籤/搜索