前言
在前端领域中,使用表单处理用户输入是常见的操作,可以使用表格让使用者登录、输入信息以及其他数据输入的任务,Angular提供了两种通过表单处理用户输入的方法:reactive
与template
,这两种方法,此篇章将会介绍他们之间的差异与用途。
Choosing an approach
reactive与template以不同的方式处理表单讯息,他们拥有各自的优劣势:
Reactive:提供对地层表单物件直接且显性
的访问,他的可扩充性、可重用性、可测试性都比template更高。template:依赖template中的指令来建立和操作底层物件,很容易新增到应用中,适合用在非常基本的表单需求与逻辑。Key differences
... | Reactive | template
------------- | -------------
建立表单模型 | 在class中建立 | 在template中建立
资料模型 | 不可变 | 可变
可预测性 | 同步 |非同步
验证 | function | 指令
Setting up the form model
Reactive与Template都会追蹤使用者互动的表单输入元素
和元件模型中的表单资料的变更
,他们共用同一套底层模块
,不同的是他们在建立和管理表单的方面不同。
Common form foundation classes
reactive和template都透过以下几本的class建立:
FormControl:追蹤单个表单元件的值和验证状态。FormGroup:追蹤一个表单控制元件集合的值和状态。FormArray:追蹤一个阵列中表单控制元件的值和状态。ControlValueAccessor:建立连接Angular FromControl与DOM的桥樑。Setup in reactice forms
若要使用reactive forms,可以在Component中定义form model,[formControl]会使用internal value accessor
将画面中特定表单元素与FormControl连接起来。
import { Component } from '@angular/core';import { FormControl } from '@angular/forms';@Component({ selector: 'app-reactive-favorite-color', template: ` Favorite Color: <input type="text" [formControl]="favoriteColorControl"> `})export class FavoriteColorComponent { favoriteColorControl = new FormControl('');}
[formControl]指令将画面中的input元件与Component中的FormControl物件连接起来,换句话说当使用者在画面上的input中输入值,会透过[formControl]将使用者输入的值传递给Conponent中的FormControl物件。
(图片来源:Angular)
Setup in template-driven forms
由于Template forms的表单形式是隐性的,所以所以需要透过NgModel
来建立并管理FormControl。
import { Component } from '@angular/core';@Component({ selector: 'app-template-favorite-color', template: ` Favorite Color: <input type="text" [(ngModel)]="favoriteColor"> `})export class FavoriteColorComponent { favoriteColor = '';}
在template form中,透过NgModel将使用者输入的数值连接到Component中的FormControl。
(图片来源:Angular)
Data flow in forms
Angular必须在我们使用form的时候将画面与Componet中的model保持同步,举例来说当使用者在画面中更改了表单中的资料时,新的值必须要立马反映在model中,同样的当model中的逻辑改变时,其结果也需要立即的反应在画面中,Reactive与Template在处理使用者或程式更改的方式有所不同。
Data flow in reactive forms
在reactive forms中,画面里的每一个表单元素都直接的连接到FormControl,画面与model的之间的数据更新是同步的,下图表示当画面更改元件中的数值时数据是如何流动到FromControl中。
(图片来源:Angular)
输入事件
。画面中表单元件的Control Value Accessor
会监听这个表单元件上的事件,并立即
将新的值传递给Component中的FormControl。Component中的FormControl会透过valueChange
这个可观察物件发送这个新的值给valueChange的订阅者。所有valueChange的订阅者收到使用者输入的新值。下图是介绍FormControl的值被更改后,如何将更改的值反映到画面中。
(图片来源:Angular)
Data flow in template-driven forms
在template forms中的每个表单元件都会连接到内部管理表单模型的指令。
下图说明了当更改画面元件后,更新的数值是如何流向model。
(图片来源:Angular)
Model.viewModelUpdate()
,发出一个ngModelChange
事件。ngModelChange事件会修改Component中双向绑定的属性的值(this.favoriteColor)下图说明当修改Component中的this.favoriteColor后,画面中的input表单是如何更新新值。
(图片来源:Angular)
--------- 变更检测开始 ---------Angular呼叫NgModel上的ngOnChanges方法。ngOnChange会将一个
非同步
更改FormControl值的任务放入伫列中。--------- 变更检测结束 ---------FormControl更新任务完成。FormControl透过valueChanges发出新值。valueChanges的订阅者收到新值。Control Value Accessor更新画面input元件中的值。
Mutability of the data model
Reactive:reactive forms透过不能改变的数据结构来保持数据行的单一化,当每一次触发更新时,FormControl都会return一个新的
数据模型而不是更新现有的数据模型,这使变更检测更有效率,因为只需要在唯一性更改(物件参考发生变化)时进行更新。Template:template forms依赖双向资料绑定,由于使用双向资料绑定时没有用来对资料模型进行追蹤的唯一性更改,因此变更检测在需要确定何时更新时效率较低。参考文献:Angular