表单验证的三种方式
本文根据官方基本使用的示例代码展开。
根据内容所需增删后最终模板代码如下:
import { Form, Input, Button } from 'antd';
const Demo = () => {
const onFinish = (values: any) => {
console.log('Success:', values);
};
const onFinishFailed = (errorInfo: any) => {
console.log('Failed:', errorInfo);
};
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
initialValues={{ remember: true }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
<Form.Item
label="Username"
name="username"
rules={[{ required: true, message: 'Please input your username!' }]}
>
<Input />
</Form.Item>
<Form.Item
label="Password"
name="password"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="Password"
name="confirmPassword"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Input.Password />
</Form.Item>
<Form.Item wrapperCol={{ offset: 8, span: 16 }}>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
);
};
ReactDOM.render(<Demo />, mountNode);
验证规则都在rules
中配置,其类型是Rule[]。官网对Rule
类型的解释是:
type Rule = RuleConfig | ((form: FormInstance) => RuleConfig);
但实际源码是:
type Rule = RuleObject | RuleRender
RuleObject
就是Rule表格介绍中的内容,而RuleRender
类型则是一个函数,其返回值还是一个RuleObject
:
type RuleRender = (form: FormInstance) => RuleObject;
FormInstance的类型,通过这个对象解构出getFieldValue
等获取字段值的方法。
了解了这些,只需记住想要实现表单数据验证,向Form.Item => rule
提供RuleObject
或RuleRender
类型的验证参数即可。
RuleObject[]
执行简单验证
1.使用在对单个字段进行较为简单的验证时,直接在rule
上配置验证规则的对象数组即可:
import { Form, Input, Button } from 'antd';
const Demo = () => {
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="Username"
name="username"
rules={[
{ required: true, message: 'Please input your username!',type: 'string' },
{ min: 5, message: "位数需大于5" },
{ max: 20, message: "位数需小于20" },
]}
>
<Input />
</Form.Item>
</Form>
);
};
2.使用validator函数增强验证
在只用RuleObject[]
的方式无法满足验证需求时,可以在rule
中配置一个含validator
函数的对象即可,编写这个函数内容时,要么使用async
返回一个promise
,要么使用函数的第三个参数callback
传出需要提示的错误信息。
用validator
重构验证:
import { Form, Input, Button } from 'antd';
const Demo = () => {
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="Username"
name="username"
rules={[
{ required: true, message: 'Please input your username!',type: 'string' },
{
// value 即是字段输入的内容
validator(rule, value, callback) {
if (value.length < 5) return callback("用户名长度不能小于5");
if (value.length > 20) return callback("用户名长度不能大于20");
callback();
},
}
]}
>
<Input />
</Form.Item>
</Form>
);
};
如果使用的是typescript,直接在rule上定义validator函数可以正确获取类型提示。但有时候我们为了代码的简洁性,需要把这个函数提取出来,这时就没有直接的类型提示了,需要手动设置类型。
import { Form, Input, Button } from 'antd';
// 导入类型
import type { ValidatorRule } from "rc-field-form/lib/interface";
const Demo = () => {
const usernameValidator: ValidatorRule = {
// 由于参数2:value 有一个隐式 any 类型,所以需要手动设置其类型
validator: (_, value: string, callback) => {
if (/\W/.test(value)) return callback("不能出现字母数字下划线以外的字符");
if (value.length < 3) return callback("用户名长度不能小于3");
if (value.length > 10) return callback("用户名长度不能大于10");
callback();
},
};
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="Username"
name="username"
rules={[
{ required: true, message: 'Please input your username!',type: 'string' },
usernameValidator
]}
>
<Input />
</Form.Item>
</Form>
);
};
提示
需要注意的是,从v4
开始,validator
的第三个参数callback
已经被弃用,包括官方的例子里也没有再继续使用这个callback
,现在推荐的做法是返回一个Promise
。
import { Form, Input, Button } from 'antd';
// 导入类型
import type { ValidatorRule } from "rc-field-form/lib/interface";
const Demo = () => {
const usernameValidator: ValidatorRule = {
validator: (rule, value) => {
if (value) {
if (/\W/.test(value)) return Promise.reject('用户名只能是字母数字下划线');
if (value.length < 3) return Promise.reject("用户名长度不能小于3");
if (value.length > 10) return Promise.reject("用户名长度不能大于10");
}
return Promise.resolve("");
}
};
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="Username"
name="username"
rules={[
{ required: true, message: 'Please input your username!',type: 'string' },
usernameValidator
]}
>
<Input />
</Form.Item>
</Form>
);
};
3.使用RuleRender函数增强验证
使用RuleRender
函数不仅仅可以验证当前字段的内容,还可以通过参数中提供的函数(比如:getFieldValue)等进行多字段数据的对比校验。使用较多的案例是密码的二次校验
!
import { Form, Input, Button } from 'antd';
// 导入类型
import type { RuleRender } from "rc-field-form/lib/interface";
const Demo = () => {
const confirmPassword: RuleRender = ({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue("password") === value) {
return Promise.resolve();
}
return Promise.reject("两次密码不一致");
},
})
return (
<Form
name="basic"
labelCol={{ span: 8 }}
wrapperCol={{ span: 16 }}
>
<Form.Item
label="Password"
name="password"
rules={[{ required: true, message: 'Please input your password!' }]}
>
<Input.Password />
</Form.Item>
<Form.Item
label="Password"
name="confirmPassword"
rules={[
{ required: true, message: 'Please confirm your password!' },
confirmPassword,
]}
>
<Input.Password />
</Form.Item>
</Form>
);
};
注:rule配置多个验证规则都是可以一起工作的。另外,usernameValidator
和confirmPassword
是不一样的,前者是一个对象,后者是一个函数。