前言
在前端应用开发中, 表单验证是比较常见的需求。接触过angular的开发者可能会对angular的表单验证印象深刻,并比较推崇。但是在vue这种渐进式,轻量化的框架里面,是否也可以实现比较友好的表单验证呢? 答案是肯定的。本次会介绍两种表单验证方式:基于elementUI的表单组件的表单验证和基于vue-form的表单验证。
直接上干货
- 基于elementui的表单验证
在国内的vue开发者中,elementUI的使用率相当广泛,当然我个人也是elementUI的使用者之一,本次先说基于elementui的表单验证。
1.1. 安装elementUI并引入elementUI
1 | yarn add element-ui |
1 | // main.ts |
1.2. 使用elementUI的表单验证
使用elementUI就比较简单了,
可以参考官方文档,这里只简述一下基本使用方法, 更加全面的api及使用可以参考elementUI-form
1 | <template> |
其中el-form上model属性对应的是表单的数据对象,rules对应的是表单的验证规则,status-icon则在表单验证过程中可以将验证状态以icon的方式显示在表单空间的右侧.
表单验证规则是一个对象,其中包括每个表单空间的key,对应模板里每个item的prop,验证规则是一个数组,即可以单个控件有多个验证规则,其中message是验证不通过的提示信息,trigger则是验证触发的方法,有change和blur等几种触发事件,亦可以传入数组表示多触发条件.
这里有演示到同步自定义验证器,验证器会回调三个参数,分别是rule,value,cb,其中value为验证器触发时当前控件的值,cb为验证是否通过的回调,当验证不通过是接受一个error对象,这时会对应验证不通过的提示,当验证通过时应当直接调用cb方法(源码在此处会校验,如果是undefined则会认为校验通过,如果按照nodejs规则传入null,则会视为校验不通过,此应为api设计缺陷)
验证器同时支持异步验证,可以在promise或者其他异步事件之后显示调用cb方法。(验证规则可以参考async-validator, elementUI表单验证基于此开发)
1.3。 提交时验证表单是否可以提交
正如大多数表单验证需求一样, 输入时表单验证是为了更好的用户体验,用户更早的发现表单输入错误,而提交时的表单验证亦是不可或缺的。
首先用vue自由的ref获得form表单的引用,其次通过elementUI为其提供的validate方法进行验证,validate方法接受一个回调函数,在回调函数里会传入两个参数,第一个参数是表单是否验证通过,第二个参数为验证对象的详情。通常我们会先判断第一个参数用来验证是否可以提交表单,第二个参数用来判断用户未验证通过的原因,以提醒用户。至此elementUI的表单验证基本介绍到这里。
- vue-form表单验证
vue-form在易用性及对ts的支持上不如elementUI友好,但是其提供了一种类似于angular表单使用习惯的验证方法,这里只是作为举例。
2.1. 安装vue-form
1 | yarn add vue-form |
2.2. 编写type文件
vue-form官方并没有提供type文件,因此我们直接引入ts环境的vue会直接报错(js环境请无视这步配置)
1 | // vue-form.d.ts |
2.3. 引入vue-form
vue-form支持两种引入方式,一种是全局use,第二种是mixins局部引入,由于自定义验证器要在引入时要声明,所以建议使用局部mixins引入,引入及使用如下
<template>
<div class="vue-form">
<vue-form :state="formState" @submit.prevent="onSubmit">
<validate tag="label">
<span>用户名</span>
<input v-model="model.username" required name="username" />
<field-messages name="username">
<span>Success</span>
<template slot="required" slot-scope="state">
<span v-if="state.$dirty || state.$submitted">请输入用户名</span>
</template>
</field-messages>
</validate>
<validate tag="label">
<span>密码</span>
<input v-model="model.password" required name="password" />
<field-messages name="password">
<div>Success!</div>
<template slot="required" slot-scope="state">
<span v-if="state.$dirty || state.$submitted">请输入密码</span>
</template>
</field-messages>
</validate>
<validate tag="label">
<span>用户名</span>
<input v-model="model.repassword" required name="repassword" />
<field-messages name="repassword">
<div>Success!</div>
<template slot="required" slot-scope="state">
<span v-if="state.$dirty || state.$submitted">请确认密码</span>
</template>
</field-messages>
</validate>
<button type="submit">Submit</button>
</vue-form>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { mixins } from 'vue-class-component'
import VueForm from 'vue-form'
@Component
export default class VueFormVal extends mixins(VueForm) {
// 表单状态
public formState: any = {}
// 表单值
public model = {
username: '',
password: '',
repassword: '',
}
public onSubmit() {
if (!this.formState.$invalid) { // 表单验证通过
// TODO xxx
} else { // 表单验证不通过
console.log(this.formState)
}
}
}
</script>
<style lang="scss" scoped>
</style>
在模板处建议使用自定义模板,一是定制性强,二是可以类似angular自定义显示提示文字的时机。这里的表单状态与angular类似。
2.4. 同上面elementUI表单验证时所讲,表单往往在提交表单时会有验证的需求和必要,此处vue-form建议我们直接拦截原生的submit事件,在拦截之后,我们可以根据formState的属性进行判断,formState的$invalid属性返回一个boolean值用以展示表单验证是否通过,我们的所有的表单字段会直接挂在在这个状态对象上,每个对象也有$invalid属性,对应各自控件的状态。
总结
在我短暂的使用过程中, vue在表单验证这块,一没有官方的实现,二社区实现方案(vue-form或elementUI)过于简陋,只能满足简单的表单校验需求,而且无论在交互上还是编程感官上,都差一点。期待后期会有比较成熟的官方或者社区实现,vue的普及势必会在后台管理或者oa等项目上大量使用,而表单这块vue只提供了v-model还是过于简陋。
