持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天。点击查看活动详情
用表单处理用户输入是许多常见应用的基础功能。 应用通过表单来让用户登录、修改个人档案、输入敏感信息以及执行各种数据输入任务。
Angular 提供了两种不同的方法来通过表单处理用户输入:响应式表单和模板驱动表单。 两者都从视图中捕获用户输入事件、验证用户输入、创建表单模型、修改数据模型,并提供跟踪这些更改的途径。
响应式表单和模板驱动表单区分
| 表单 | 详情 |
|---|---|
| 响应式表单 | 提供对底层表单对象模型直接、显式的访问。它们与模板驱动表单相比,更加健壮:它们的可扩展性、可复用性和可测试性都更高。如果表单是你的应用程序的关键部分,或者你已经在使用响应式表单来构建应用,那就使用响应式表单。 |
| 模板驱动表单 | 依赖模板中的指令来创建和操作底层的对象模型。它们对于向应用添加一个简单的表单非常有用,比如电子邮件列表注册表单。它们很容易添加到应用中,但在扩展性方面不如响应式表单。如果你有可以只在模板中管理的非常基本的表单需求和逻辑,那么模板驱动表单就很合适。 |
常用表单基础类
| 基类 | 详情 |
|---|---|
| FormControl | 追踪单个表单控件的值和验证状态。 |
| FormGroup | 追踪一个表单控件组的值和状态。 |
| FormArray | 追踪表单控件数组的值和状态。 |
| ControlValueAccessor | 在 Angular 的 FormControl 实例和内置 DOM 元素之间创建一个桥梁 |
建立响应式表单
对于响应式表单,你可以直接在组件类中定义表单模型。[formControl] 指令会通过内部值访问器来把显式创建的 FormControl 实例与视图中的特定表单元素联系起来。
下面的组件使用响应式表单为单个控件实现了一个输入字段。在这个例子中,表单模型是 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('');
}
建立模板驱动表单
在模板驱动表单中,表单模型是隐式的,而不是显式的。指令 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 = '';
}
表单中的数据流 当应用包含一个表单时,Angular 必须让该视图与组件模型保持同步,并让组件模型与视图保持同步。当用户通过视图更改值并进行选择时,新值必须反映在数据模型中。同样,当程序逻辑改变数据模型中的值时,这些值也必须反映到视图中。
响应式表单和模板驱动表单在处理来自用户或程序化变更时的数据处理方式上有所不同。下面的这些原理图会以上面定义的 favorite-color 输入字段为例,分别说明两种表单各自的数据流。
响应式表单中的数据流
在响应式表单中,视图中的每个表单元素都直接链接到一个表单模型(FormControl 实例)。 从视图到模型的修改以及从模型到视图的修改都是同步的,而且不依赖于 UI 的渲染方式。
这个视图到模型的图表展示了当输入字段的值发生变化时,数据流是如何从视图开始经过下列步骤进行流动的。
-
最终用户在输入框元素中键入了一个值,这里是 "Blue"。
-
这个输入框元素会发出一个带有最新值的 "input" 事件。
-
这个控件值访问器 ControlValueAccessor 会监听表单输入框元素上的事件,并立即把新值传给 FormControl 实例。
-
FormControl 实例会通过 valueChanges 这个可观察对象发出这个新值。
-
valueChanges 的任何一个订阅者都会收到这个新值。
数据更新。
-
favoriteColorControl.setValue() 方法被调用,它会更新这个 FormControl 的值。
-
FormControl 实例会通过 valueChanges 这个可观察对象发出新值。
-
valueChanges 的任何订阅者都会收到这个新值。
-
该表单输入框元素上的控件值访问器会把控件更新为这个新值。