react项目Ant design-Form表单自定义校验
1. 需求:
- 密码框的校验提示自定义:
- 非空状态下,需判断输入的密码长度、字符规则是否符合;对于符合规则的校验,将图标颜色修改为#28C81F;
- 密码框为空的状态下,使用form组件自带的错误提示;
2. 效果图:


3. 实现代码
1) 逻辑代码
import React, { useState } from 'react';
import { Button, Form, FormProps, Input, Space } from 'antd';
import { CheckCircleFilled } from '@ant-design/icons';
type FieldType = {
password?: string;
}
type passwordRulesType = {
length: boolean;
uppercase: boolean;
specialChar: boolean;
complexity: boolean;
}
export const SignInForm: React.FC<null> = () => {
const [form] = Form.useForm<FieldType>();
const onFinish: FormProps<FieldType>['onFinish'] = (values: FieldType) => {
console.log('校验成功,下一步:', values);
};
const onFinishFailed: FormProps<FieldType>['onFinishFailed'] = (errorInfo) => {
console.log('onFinishFailed:', errorInfo);
};
const [passwordRules, setPasswordRules] = useState<passwordRulesType>({
length: false,
uppercase: false,
specialChar: false,
complexity: false
});
const validatePassword = (pwd: string) => {
const length = pwd.length >= 8 && pwd.length <= 20;
const uppercase = /[A-Z]/.test(pwd);
const specialChar = /[!@#$%^&*(),.?":{}|<>]/.test(pwd);
const complexity = uppercase && specialChar && /\d/.test(pwd);
setPasswordRules({
length,
uppercase,
specialChar,
complexity
});
return Object.values(passwordRules).every(item => item === true);
};
const renderPasswordRules = () => (
<div className='C-render-password-rules'>
<Space>
<CheckCircleFilled style={{ color: passwordRules.length ? '#28C81F' : '#D9D9D9' }} />
<span style={{ color: '#D9D9D9' }}>支持8 - 20个字符,长度至少为8个字符</span>
</Space>
<Space>
<CheckCircleFilled style={{ color: passwordRules.uppercase ? '#28C81F' : '#D9D9D9' }} />
<span style={{ color: '#D9D9D9' }}>至少包含一个大写字母</span>
</Space>
<Space>
<CheckCircleFilled style={{ color: passwordRules.specialChar ? '#28C81F' : '#D9D9D9' }} />
<span style={{ color: '#D9D9D9' }}>至少包含一个特殊字符</span>
</Space>
<Space>
<CheckCircleFilled style={{ color: passwordRules.complexity ? '#28C81F' : '#D9D9D9' }} />
<span style={{ color: '#D9D9D9' }}>必须包含数字、英文字母和特殊符号</span>
</Space>
</div>
);
return (
<>
<div className={'C-signIn-form flex flex-col items-center'}>
<div className='w-full flex flex-col items-center'>
<div style={{ fontSize: '36px' }}>Create your account</div>
</div>
<div className='w-[330px] mt-[25px]'>
<Form
form={form}
layout='vertical'
size='large'
style={{ maxWidth: '330px' }}
onFinish={onFinish}
onFinishFailed={onFinishFailed}
>
<Form.Item<FieldType>
label='Password'
name='password'
rules={[
({ getFieldValue }) => ({
validator(_, value) {
if (!value) {
setPasswordRules({
length: false,
uppercase: false,
specialChar: false,
complexity: false
});
return Promise.reject(new Error('Please enter your password'));
}
if (value === getFieldValue('password')) {
if (!validatePassword(value)) {
return Promise.reject(new Error(''));
}
}
return Promise.resolve();
}
})
]}
>
<div>
<Input.Password placeholder='Enter your password' />
{renderPasswordRules()}
</div>
</Form.Item>
<Form.Item style={{ marginTop: '25px' }}>
<Button type='primary' block onClick={() => form.submit()}>Next</Button>
</Form.Item>
</Form>
</div>
</div>
</>
);
};
2) 样式
.C-signIn-form {
.ant-form-vertical .ant-form-item:not(.ant-form-item-horizontal) .ant-form-item-label {
font-weight: bold;
padding: unset;
.ant-form-item-required::before {
content: '' !important;
}
}
}
.C-render-password-rules {
position: absolute;
top: 0;
left: calc(100% + 20px);
width: max-content;
display: flex;
flex-direction: column;
gap: 5px;
}
4. 注意事项:
<Form.Item>
组件的内容如果需要自定义,需要保持只有一个根元素;Button
组件type='primary'
需添加onClick={() => form.submit()}
才会在点击按钮时触发表单的提交;