1、表单校验是非常常见的需求,能够有效的拦截大部分的错误数据,提升效率。
2、快速的给使用者提示和反馈,用户体验感非常好。
3、成熟的表单校验框架,开发效率高,bug少。
最近使用的是vue3+antdv的架子,仔细探究一下表单校验的问题,总结一下。
框架可能不同,主要看核心问题,如果有帮助,欢迎一键三连。【春花秋时知多少】
首先查看官网的 模版,
构建了一个表单,大概意思是直接写rules就可以使用了,我的目标是这个字段需要长度限制,
第一个常见错误,rules的位置错误,直接在item里面加了rule(或者rules ),都是无效的,需要加在表单上。
(注:antd文档是在表单项里面配置rules的,一般会对比两个组件的文档,有时候真的有用!!!)
...
上面的写法就是无效的,必须要放在 a-form
,也就是表格上面,不能放在表单项上面。
...
对应rules绑定位置,使用:rules 绑定对象
那它如何区分是哪个字段的校验规则呢?
rules是一个对象,对象的属性名对应字段的name名即可(类似map的key),通过key去找规则。
而且对象的值是一个对象数组,可以创建多个规则叠加,不用所有规则写到一个对象里面。
const rules = {
name: [
{
required: true,
message: "ass",
},
],
passwd: [
{
min: 5,
message: "need",
},
],
};
这个官方只给的例子,不是很清楚,但是它说本质上是使用的 async-validator
然后看了下,大概有这几个点需要注意,基本就能完成大部分的规则校验。
1、类型判断,比如校验值必须是数字,用这个就可以快速限定类型。支持的类型如下
string
number
boolean
method
regexp RegExp
integer
float
array
object
enum
date
url
hex
email
any
还支持正则,对于对象和数组,还可以进一步处理,非常方便。
对象可以使用 fields
来限定属性
const descriptor = {
address: {
type: 'object',
required: true,
options: { first: true },
fields: {
street: { type: 'string', required: true },
city: { type: 'string', required: true },
zip: { type: 'string', required: true, len: 8, message: 'invalid zip' },
},
},
};
数组 可以使用下标位置来限定
const descriptor = {
roles: {
type: 'array',
required: true,
len: 3,
fields: {
0: { type: 'string', required: true },
1: { type: 'string', required: true },
2: { type: 'string', required: true },
},
},
};
数组还可以使用统一的defaultField
来处理每一个
const descriptor = {
urls: {
type: 'array',
required: true,
defaultField: { type: 'url' },
},
};
2、trigger 指定校验时机
文档上只支持 change(改变) 和 blur(聚焦),就是输入的时候,和失去焦点的时候,比如提交的时候,根据需求选择即可。
经测试,默认不处理 是 trigger: 'change'
,输入校验
可以使用数组,来同时满足多个 trigger: ['blur', 'change']
,
单个 trigger: 'blur'
本来都写好了,发现出现的逻辑不对,最简单的例子都实现不了。
const rules = {
name: [
{
required: true,
message: "must need",
},
{
min: 5,
message: "least 5.",
},
],
};
针对同一个字段,两条规则:
第一个规则:必填,如果没填就提示第一个,
第二个规则: 至少5位。
结果只有第一个提示,而且一直提示,不会消失。
我甚至是怀疑是只有配置了required: true,
才能正常使用,显然不是,这个表示的是不能为空。即使算输入合法的也会提示,根本没有校验逻辑。
后面查了半天,还需要配置一个 :model="formState"
,即需要传递表单对象过去,校验表单项的值从这里面取,应该是而不能直接获取表单项的值。这个 :model
就是需要把表单对象传递过去。
{{ item.value }}
-->
...
const formState = reactive({
name: "",
region: undefined,
date1: undefined,
delivery: false,
type: [],
resource: "",
desc: "",
});
const rules = {
name: [
{
required: true,
message: "must need",
},
{
min: 5,
message: "least 5.",
// trigger: ["change", "blur"],
// validator: checkeNickName,
},
],
};
这个问题困扰了我半天,写出来,希望能帮到大家。
这个很简单,直接写一个自定义校验方法就行了。
然后校验规则里面指定自己的校验方法, validator: checkeNickName,
即可
(注:就是用这个方法,然后debug出上面的mode未设置的问题,自定义方法里面的value一直是undifine,-。-)
const checkeNickName = function (rule, value, callback) {
console.log(rule, value, callback);
if (value) {
if (value.length > 5) {
return Promise.reject("用户昵称长度应小于5个字符");
} else {
return Promise.resolve();
}
} else {
return Promise.reject("请输入用户昵称");
}
};
const rules = {
name: [
{
required: true,
message: "must need",
},
{
min: 5,
message: "least 5.",
validator: checkeNickName,
},
],
};
拿到了值,自己怎么处理就好写了,成功 返回 return Promise.resolve();
失败返回 return Promise.reject("用户昵称长度应小于5个字符");
,里面的参数是提示信息,可以自定义
1、规则配置位置要正确,大部分问题都是配置错误,尽量搞懂每个配置的作用
2、本质上是对async-validator 的封装,可以从源头查询问题
3、antdv表单校验需要传递表单对象过去,这个是特有的规定,按照要求编写。
4、自定义校验,只需要写自定义校验方法 function (rule, value, callback)
,然后在rules的对象里面 使用 validator: checkeNickName,
调用这个方法即可