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

疑问

  • 若是有哪里描述的有问题或者不对的请多提宝贵意见
相关文章
相关标签/搜索