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实现类
,当找到后,经过将一些变动须要出发的函数告知实现类
而创建了关联
源码注释
疑问
欢迎关注本站公众号,获取更多信息