Angular 表单

问题描述

Web开发中,表单一直是一个重要的话题。

AngularJS中,我们可以使用双向数据绑定很简单地完成表单的开发,但是会带来严重的性能问题,而Angular对于表单的设计,让我们的表单在保持性能的同时更优雅。

实例

我们以一个最简单的登录表单为例来学习Angular中的表单:

思想

这就是Angular的表单思想,一个FormGroup管理整个表单,同时FormControl管理表单内的各个元素。

Create

导入表单模块:

基础的HTML表单代码:

Angular Form

略加修改:

Angular Form

当我们的应用导入FormsModule时,form就不再是原生的form了,而是Angular重写过的NgForm组件,就像在AngularJS中使用的form其实是被框架扩展的指令。

所以我们可以为form添加NgForm组件定义的输入输出。

这是NgForm的官方api文档描述,导出ngForm,然后输出ngSubmit事件。

这里用到了导出的ngForm,并为其取名为myForm,所以传给onSubmitmyForm其实就是导出的ngForm,当业务逻辑非常简单的情况下可以这样写,直接用导出的ngForm,就相当于使用一个默认配置好的对象。


两个input用到了ngModel指令,该指令会为该元素创建一个默认的FormControl

onSubmit(myForm: NgForm): void {
    console.log(myForm);
    console.log(myForm.value);
}

提交表单,打印,可以查看myForm中的许多属性,同时它的value属性就是表单内容。

点开NgForm,其实除了表单的值外,还有dirtyerrorinvalid等属性方便我们对表单进行验证。

点开controls属性,我们可以看到该表单中的FormControl


我们尝试将input中原来添加的ngModel指令删除,再打印。可以看到该表单中没有FormControl

这就验证了我们之前的猜想,ngModel指令默认的单向数据绑定,其实就是为我们创建了一个默认的FormControl用于控制该元素的值。

在不考虑表单验证的前提下,这个基本的新增表单应该就算完成了,在onSubmit中获取表单的值,然后包装对象调用Service请求api

Update

新增时因为没有初始的数据,所以直接使用默认创建的FormGroupFormControl就行了,但是编辑时是有初始化的数据的,所以我们就需要创建自定义的FormGroupFormControl

这里是Angular权威指南中推荐初始化表单的方式,当然也可以去new

还是规范,构造和初始化分开,constructor中使用formBuilder构造FormGroupFormControl

myForm: FormGroup;

constructor(formBuilder: FormBuilder) {
    this.myForm = formBuilder.group({
        email: '',
        password: ''
    });
}

初始化,为FormControl设置数据,实际开发应该是从后台获取数据然后设置,这里为了演示方便,直接setValue

ngOnInit() {
    this.getOriginData();
}

getOriginData(): void {
    this.myForm.setValue({
        email: '[email protected]',
        password: 'this is password'
    });
}

数据有了,接下来就是将数据绑定到组件上。将myForm作为参数传给组件,ngSubmit不变。

绑定成功!

Validate

修改代码,我们删除邮箱与密码的初始化代码,让其为默认的空值。

纵使风云变幻,始终不离其宗。

Valid: {{ myForm.controls['email'].valid }}
Touch: {{ myForm.controls['email'].touched }}
Valid: {{ myForm.controls['password'].valid }}
Touch: {{ myForm.controls['password'].touched }}

我们想对这两个输入框进行验证,直接在初始化时设置验证条件:

constructor(formBuilder: FormBuilder) {
    this.myForm = formBuilder.group({
        email: ['', Validators.compose([
            Validators.required,
            Validators.email
        ])],
        password: ['', Validators.required]
    });
}

实现验证:邮箱的空验证与邮箱格式验证,密码的空验证。

然后符合我们以往的开发规范,用一个ngIfp标签,然后当不合法且触碰过时,显示提示信息。

扩展验证

在以往的AngularJS项目里,我们只能用已有的验证规则,但是现在更强大了!

其实,我们上面用到的requiredemail等的验证规则都是框架为我们提供的已有的验证函数,翻开ValidatorFn - Angular,有ValidatorFn接口,实现该接口,即可实现自定义的验证方法!

总结

双向数据绑定的思考:

既然表单都设计得如此强大,我们又何必拘于双向数据绑定,双向数据绑定是我们实现软件功能的一种方式,但不是唯一方式。

如果使用双向数据绑定,那肯定比我上面说的简单许多,但是自从学习了软件测试,渐渐明白了,其实我们在做软件开发时,与我们平常在学校写代码是不一样的。

就像今天吴老师讲的例子:求e50次方。如果在学校,我们可能直接一个for循环50次然后一次一次去乘。

但是如果在公司,我们可能就会先算e的平方,然后再算出e的四次方e的八次方,然后根据几个已有的去组合需要的结果,这会让性能大幅提升。

这是美团点评团队优化小程序的一篇博客:

或许,之前的我们学习了很多知识,学会了不少框架,也写过许多代码,但是我对自己的评价还是程序员。今天,我才明白,何为软件工程师?!

立个小目标:以后写代码时多考虑一点,优秀的软件工程师写出的代码是能够直接上线的。

你可能感兴趣的:(表单,angular)