react如何校验表单
表单校验方法
在React中校验表单可以通过多种方式实现,包括内置HTML5校验、手动校验和使用第三方库。以下是几种常见的方法:
使用HTML5内置校验
HTML5提供了一些内置的表单校验属性,可以直接在表单元素上使用:
<input
type="text"
required
minLength="3"
maxLength="20"
pattern="[A-Za-z]+"
/>
手动校验
在表单提交或字段变更时手动校验字段:
function validateForm(values) {
const errors = {};
if (!values.username) {
errors.username = '用户名不能为空';
} else if (values.username.length < 3) {
errors.username = '用户名至少3个字符';
}
return errors;
}
使用React状态管理
利用React的state来跟踪表单错误状态:
const [errors, setErrors] = useState({});
const handleSubmit = (e) => {
e.preventDefault();
const validationErrors = validateForm(formData);
if (Object.keys(validationErrors).length > 0) {
setErrors(validationErrors);
return;
}
// 提交表单
};
第三方库校验
Formik + Yup
Formik是一个流行的表单处理库,与Yup校验库配合使用:
import { Formik, Form, Field } from 'formik';
import * as Yup from 'yup';
const validationSchema = Yup.object().shape({
email: Yup.string().email('无效的邮箱').required('必填'),
password: Yup.string().min(6, '密码至少6位').required('必填')
});
<Formik
initialValues={{ email: '', password: '' }}
validationSchema={validationSchema}
onSubmit={values => console.log(values)}
>
{({ errors, touched }) => (
<Form>
<Field name="email" />
{errors.email && touched.email && <div>{errors.email}</div>}
<Field name="password" type="password" />
{errors.password && touched.password && <div>{errors.password}</div>}
<button type="submit">提交</button>
</Form>
)}
</Formik>
React Hook Form
另一个轻量级的高性能表单库:
import { useForm } from 'react-hook-form';
function Form() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = data => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input {...register('username', { required: true, minLength: 3 })} />
{errors.username?.type === 'required' && <p>用户名必填</p>}
{errors.username?.type === 'minLength' && <p>用户名至少3个字符</p>}
<input type="submit" />
</form>
);
}
实时校验策略
在用户输入时实时校验可以提供即时反馈:
const handleChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
// 实时校验
const validationErrors = validateField(name, value);
setErrors(prev => ({ ...prev, [name]: validationErrors[name] }));
};
错误信息展示
统一管理错误信息的展示方式:
{errors.username && (
<div className="error-message">{errors.username}</div>
)}
使用CSS增强错误提示的视觉效果:
.error-message {
color: red;
font-size: 0.8rem;
margin-top: 0.2rem;
}
高级校验场景
异步校验
需要调用API验证用户名是否可用:
const validateUsername = async (value) => {
const response = await fetch(`/api/check-username?username=${value}`);
const data = await response.json();
return data.available ? null : '用户名已存在';
};
跨字段校验
验证密码和确认密码是否匹配:
const validationSchema = Yup.object().shape({
password: Yup.string().required('必填'),
confirmPassword: Yup.string()
.oneOf([Yup.ref('password'), null], '密码不匹配')
.required('必填')
});
性能优化
对于大型表单,可以优化校验性能:
// 只在字段失去焦点时校验
const handleBlur = (e) => {
const { name, value } = e.target;
const validationErrors = validateField(name, value);
setErrors(prev => ({ ...prev, [name]: validationErrors[name] }));
};
无障碍支持
确保校验信息对屏幕阅读器友好:
<input
aria-invalid={!!errors.email}
aria-describedby="email-error"
/>
{errors.email && (
<div id="email-error" role="alert">
{errors.email}
</div>
)}






