Angular-响应式表单和模版驱动式表单

1、响应式表单和模板驱动型表单之间的差异

答:

a、创建的方式不同:响应式表单实在组件类中预先定义的,而模板驱动型表单是通过ngModel指令创建的

b、数据模型特点不同:响应式表单的数据模型遵循不可变性、结构化,而模板驱动型表单数据模型是可变的、非结构化的

c、数据流不同:响应式表单的数据流是同步的,因为其通过formControl实例的setValue方法直接更新表单元素的值,而模板驱动型表单的数据流是异步的,其是通过触发ngModel指令内部的formControl实例的setValue方法,并且调用NgModel.viewToUpdate方法激活ngModelChange事件更新模型的值

d、表单验证的方式不同:响应式表单采用向formControl构造函数中传递函数的方式进行校验,而模板驱动型表单则通过在dom元素上绑定指令的方式添加校验,该指令是注册为NG_VALIDATORS提供者类型的指令,且内部实现了Validator类

2、响应式表单的创建

答:

a、在组件类中定义表单数据模型,预先声明好需要使用的表单元素

b、在html页面中使用[formControl]指令来绑定对应的单个的表单控件,使用formControlName指令来绑定一个formGroup对象中的某个表单控件属性

c、在组件类中定义getter函数来访问formGroup对象中的某个表单控件实例

3、模板驱动型表单的创建

答:在html页面中直接使用[(ngModel)]指令绑定数据变量

a、可以通过#myModel="ngModel"的方式导出ngModel创建的formControl实例,从而在模板中使用该formControl实例的方法和属性

4、响应式表单的数据流分析

答:数据流分为两个方向:

> 由视图流向数据模型

a、用户向表单元素输入值,并触发表单元素对应的input、change事件

b、附着在该表单元素上的控件值访问器(ControlValueAccessor)会监听该表单元素发出的事件

c、在监听到事件时控件值访问器会将表单元素的最新值传递给FormContrl实例,并执行setValue()方法

d、在执行FormControl实例的setValue()方法之后会通过formControl实例的valueChanges可观察对象将新值传递出去

e、凡是订阅了该valueChanges可观察对象的订阅者都会收到该表单元素的最新值

> 由数据模型流向视图

a、在组件类中调用了formControl实例的setValue()方法,更新数据模型的值

b、在更新值之后会通过formControl实例的valueChanges可观察对象,将新值发送出去

c、凡是订阅了该formControl实例的valueChanges可观察对象的订阅者都会收到新值

d、同时会调用控件值访问器(ControlValueAccessor)的writeValue()方法更新视图中对应表单控件元素的值

5、模板驱动型表单的数据流分析

答:数据流分为两个方向:

>由视图流向数据模型

a、用户在表单元素中输入值,并触发表单元素的input、change等事件

b、附着在该表单元素上的控件值访问器会触发由ngModel生成的formControl实例的setValue()方法,并通过valueChanges()可观察对象发出新值

c、凡是订阅了该可观察对象的订阅者就会收到该新值

d、同时控件值访问器还会通过NgModel.viewToModelUpdate()方法触发ngModelChange事件

e、由于[(ngModel)]实现了双向数据绑定的规则,因此可以更新绑定的变量的值

>由数据模型流向视图

a、在组件类中修改绑定到dom中表单元素的变量的值

b、变更检测开始

c、在变更检测期间发现变量值的变化,angular就会触发NgModel指令中的ngOnChanges声明周期钩子,同时会将一个用于修改内部formControl实例值的异步任务排入队列

d、变更检测结束

e、在下一个变更检测周期中,执行上一个周期中排入队列的修改内部formControl值的异步任务,即调用formControl实例的setValue()方法设置值

f、formControl实例通过valueChanges可观察对象发送新值,有关订阅者都可收到新值

g、在设置formControl实例的值后,会调用控件值访问器(ControlValueAccessor)的writeValue()方法更新dom中表单控件元素的值

注意:viewToModelUpdate()方法继承自NgComtrol类,ngModel指令会创建一个FormControl实例,并绑定到对应的表单控件元素上

注意:ControlValueAccessor即控件值访问器定义一个接口,充当angular表单API和DOM中的原生表单元素之间的桥梁