携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情
最近一直在忙着做项目,在这个过程中也遇到了很多问题,之前虽然也有做笔记总结,但从未发过文章,这是第一次尝试,既为分享,也为记录,写得不好请各位多多指正。
言归正传,相信大家经常都会遇到要处理表单验证的环节,而我在最近的项目中也遇到需要做表单验证的业务,在此做一下小菜鸟的分享。
先上效果图:
表单校验前的准备
首先可以先参考Element Plus官网表单组件的校验表单基本格式
准备过程总结为如下三步:
-
从element-plus中引入类型FormInstance和FormRules,并把表单对象的节点设置为FormInstance类型,表单内对所有参数约束的总规则(rules)设置为FormRules类型
-
定义包含表单内各参数的响应式数据对象ruleForm,并把ruleForm和rules在表单标签的属性中进行单向数据绑定。此外需为表单参数对应的item设置相应的prop和v-model绑定对应ruleForm的参数
-
定义好提交表单的验证函数,官网例子中为submitForm函数和resetForm函数
<template>
<div id="validator-form">
<!-- 以此为例 为表单对象设置ref以便后续获取该节点对象
并为表单对象添加ruleForm和rules的单向数据绑定 此外给姓名参数的item添加name的prop
以及v-model数据双向绑定ruleForm对应名的参数-->
<el-form
ref="ruleFormRef"
:model="ruleForm"
:rules="rules"
label-width="520px"
class="demo-ruleForm"
:size="formSize"
status-icon
>
<el-form-item label="姓名" prop="name">
<el-input v-model="ruleForm.name" placeholder="请输入名字"/>
</el-form-item>
...
</el-form>
</div>
</template>
<script lang="ts" setup>
import { reactive, ref } from "vue";
// 引入类型
import type { FormInstance, FormRules } from "element-plus";
const formSize = ref("default");
// 获取表单对象并设置为FormInstance类型
const ruleFormRef = ref<FormInstance>();
// 定义包含表单内各参数的响应式数据对象 用于保存表单参数
const ruleForm = reactive({
name: "",
sex: "",
height:"",
weight:"",
phone: "",
time: "",
email: "",
birthday:""
});
// 定义包含所有参数规则的rules常量并设置为FormRules类型
const rules = reactive<FormRules>({...})
...
// 表单校验函数
const submitForm = async (formEl: FormInstance | undefined) => {
if (!formEl) return;
await formEl.validate((valid, fields) => {
if (valid) {
// 校验成功
console.log("submit!");
} else {
// 校验失败
console.log("error submit!", fields);
}
});
};
//清除校验效果并且清空表单参数的函数
const resetForm = (formEl: FormInstance | undefined) => {
if (!formEl) return;
formEl.resetFields();
};
</script>
表单校验的重点:定义规则
1.input输入框原生自带的type规则约束
例如type="password",原生自动的type类型可以参考这个::输入(表单输入)元素 - HTML(超文本标记语言) | MDN
2.根据不同参数指定对应的自定义规则
举一个简单的例子:
const rules = reactive<FormRules>({
name: [
{ required: true,type:'string', message: "姓名不能为空", trigger: "blur" },
{ pattern:/[\u4e00-\u9fa5]/,min: 2, max: 15, message: "姓名格式错误", trigger: "blur" },
],
// 也可以写出这种形式 需要定义validatename函数
//name: [{ validator: validateName, trigger: 'blur' }],
...
})
/*
const validateName = (rule: any, value: any, callback: any) => {
if (value === '') {
callback(new Error('请重新输入名字'))
} else {
if (ruleForm.name !== '') {
if (!ruleFormRef.value) return
ruleFormRef.value.validateField('checkName', () => null)
}
callback()
}
} */
required:是否为必填项,如不设置,则会根据校验规则确认。
type的类型与原生input的type类型不同,它限制对应参数的类型,其可选项有如下:
| string | 必须是类型string |
| number | 必须是类型number |
| boolean | 必须是类型boolean |
| method | 必须是类型function |
| regexp | 必须是RegExp创建新的时不产生异常的实例或字符串RegExp |
| integer | 必须是类型number和整数 |
| float | 必须是类型number和浮点数 |
| array | 必须是由 确定的数组Array.isArray |
| object | 必须是 typeobject而不是Array.isArray |
| enum | 值必须存在于enum |
| date | 值必须是有效的Date |
| url | 必须是类型url |
| hex | 必须是类型hex |
必须是类型email | |
| any | 可以是任何类型 |
但是仅仅靠type的限制是远远无法满足业务需求的,因此
pattern的存在就显得尤为重要,它代表着rule 属性指示值必须匹配才能通过验证的正则表达式。
通过正则表达式我们可以实现对手机号码、邮箱等各项数据的合法性进行最基本的正确性校验。
3.几个小小的注意点
- 要验证字段的确切长度,请指定len属性。如果该
len属性与min和max范围属性结合使用,len则优先。 - 使用
min和max属性定义范围时,对于string和array类型是针对其length, 对应number类型则要求它的值不能小于min或大于max - 此外如果需要验证深层对象属性,还可以通过将嵌套规则分配给规则的属性来验证属于
object或类型的规则。 - el-input里的v-model后可以跟(.number)这会把输入的内容转为number类型,即例如v-model.number="xxx.xxx"
另一种的表单验证:async-validator
其基本用法是:定义描述符,将其分配给模式并将要验证的对象和回调函数传递给validate模式。
与上述的方法在规则限定上大体相识,使用前记得先install async-validator
除了可以像常规方法以对象的形式那般使用type、pattern正则表达式限制,它还可以以函数的形式使用,如果业务十分复杂有多重验证的话,使用这个方法会更合适,通过官方文档给出的example可以清晰看到该方法可以将多个规则组成为对象数组,代码如下:
const descriptor = {
email: [
{ type: 'string', required: true, pattern: Schema.pattern.email },
{
validator(rule, value, callback, source, options) {
const errors = [];
// test if email address already exists in a database
// and add a validation error to the errors array if it does
return errors;
},
},
],
};
官方文档地址:GitHub - yiminghe/async-validator: validate form asynchronous
个人总结:
本次项目中做表单验证的过程,我发现官方文档永远是咋们最可靠的帮手,看懂官方文档真的基本可以解决遇到的绝大部分问题。
最后,奉上我最近比较喜欢的一句话:从不胜利的人很少失败,从不攀登的人很少跌倒。 希望大家都不畏失败,不怕跌倒。