ngModel源码浅解

bitflyer
• 阅读 3136

前言

  • 之前看过vue的双向绑定原理,并实现过简易的demo,但是很少见过有讲解angular下,双向绑定是如何实现的,所以看了下NgModel源码,发现大同小异,特来说下
  • 目前来说只说下ngModel是如何实现的,不涉及属性绑定及指令方面的知识
  • 本篇文章需要知道如下知识才可以阅读
自定义表单控件
响应式表单之FormControl

一个ngModel,使用了几个指令?

  • 一般当这么说,那么肯定意味着使用了不只一个指令,否则也不会浪费时间说一个确定的事实
组件也是继承于指令的,所以这么说应该也不算错
  • NgModelControlValueAccessor实现类,当你要使用NgModel时,实际上是使用了两个指令
  • NgModel 负责注册一些函数,所有ControlValueAccessor实现类实现的4个方法(一个可选禁用方法),最终都是通过NgModel的来使用的
  • ControlValueAccessor实现类是规定绑定的内部逻辑,比如什么时候发送值被变更,当出现值写入时如何处理

流程示意图

ngModel源码浅解

注册

  • 所谓注册就是当值变更时.实现类应该用哪些方法去通知已经变更
  • 实现类中的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

疑问

  • 如果有哪里描述的有问题或者不对的请多提宝贵意见
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Easter79 Easter79
3年前
swap空间的增减方法
(1)增大swap空间去激活swap交换区:swapoff v /dev/vg00/lvswap扩展交换lv:lvextend L 10G /dev/vg00/lvswap重新生成swap交换区:mkswap /dev/vg00/lvswap激活新生成的交换区:swapon v /dev/vg00/lvswap
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
bitflyer
bitflyer
Lv1
不是花中偏爱菊,此花开尽更无花。
文章
2
粉丝
0
获赞
0