应用场景
我们经常会结合 Modal 和 Form 来实现一些对话框内提交信息的需求,而有些信息是需要在填写完成后立即校验的,看上去像这样:
属性准备
要实现这样的功能,需要准备以下属性:
属性 | 说明 | 值 |
validateTrigger | 字段校验的时机 | onChange/onBlur/onFocus/… |
validator | 自定义校验函数 | rules 中的自定义校验,接收 Promise 作为返回值 |
validateStatus | 校验状态 | success/warning/error/validating |
hasFeedback | 展示校验状态图标(建议只配合 Input 组件使用) | boolean |
help | 提示信息 | 设置后,会覆盖之前自动生成的提示信息 |
注意, 使用上述这些属性后,相当于校验的状态、提示信息等完全是受控的,不再接受 form 表单默认的校验功能,需要我们自己手动实现。
代码实现
结构
const [validateStatus, setValidateStatus] = useState(undefined); // 受控的校验状态
const [validateHelp, setValidateHelp] = useState(''); // 校验的提示信息
//(返回 Promise)
const handleIdValidator = () => {
// ...实现自定义校验方法
}
<Form.Item
label="ID"
name="id"
hasFeedback
validateTrigger="onBlur" // 输入完成, 失去焦点后开始校验
validateStatus={validateStatus}
help={validateHelp}
rules={[
{ required: true },
{ validator: handleIdValidator },
]}
>
<Input placeholder="请输入ID" />
</Form.Item>
自定义校验方法
接下来我们来实现一个自定义的校验方法:
const handleIdValidator = async (_, value) => {
setValidateHelp('ID校验中......');
// step1. 非空校验
if (value === undefined || !value.trim()) {
setValidateStatus('error');
setValidateHelp('请输入产商ID!');
throw new Error();
}
// step2. 开始校验
setValidateStatus('validating');
try {
const res = await api(value); // todo 后端校验请求
if (res) {
setValidateStatus('success');
setValidateHelp(undefined);
return res;
}
} catch (e) {
setValidateStatus('error');
setValidateHelp('无效的厂商ID!');
throw new Error(e); // ↑ 错误信息会显示手动设置的 help(不会显示 Error 中的值)
}
}
// mock 一个校验请求
const api = (value) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (value % 2) resolve('校验成功');
reject('无效的ID');
}, 800);
});
};
提交优化
在实现功能后,点击确定按钮会发现 form 表单又重新校验了一遍。是这因为大部分情况下,我们的提交按钮设置了htmlType="submit"
,该属性会在点击时默认提交 form 表单数据,此时 antd 的 form 会自动进行验证,如果校验成功,则会调用 onFinish
配置的回调。而这里,我们的信息都是必填且在填写时已经校验过了,所以按钮可以移除 submit
属性,直接获取 form 表单数据,进行提交。
const submitForm = async () => {
// 直接获取所有 form 表单数据
const formData = form.getFieldsValue();
try {
await api(formData); // todo
} catch (error) {
console.log('🚀 ~ error', error);
} finally {
// 重置
setValidateStatus(undefined);
setValidateHelp(undefined);
}
};
参考资料