//增加身份证校验规则
import { useState, useCallback } from 'react';
// 自定义Hook:表单验证
const useName = (initialValue = '', type='') => {
// 状态管理:字段值和错误信息
const [value, setValue] = useState(initialValue);
const [error, setError] = useState('');
const [touched, setTouched] = useState(false);
// 验证函数:检查是否为空
const validateField = useCallback((fieldValue) => {
if (!fieldValue || fieldValue.trim() === '') {
return '请输入必填项';
}
//如果是身份证号码,进行身份证号校验:15位纯数字或18位(前17位数字 + 最后一位数字 or X or x)
if(type="certNo") {
const certNoReg = /^(?:\d{15}|\d{17}[\dXx])$/
if(!certNoReg.test(fieldValue.trim())){
return '身份证号码格式不正确';
}
}
return ''; // 空字符串表示验证通过
}, [type]);
// 处理输入变化
const handleChange = useCallback((e) => {
const newValue = e.target.value;
setValue(newValue);
// 如果字段已经被触摸过,实时验证
if (touched) {
const validationError = validateField(newValue);
setError(validationError);
}
}, [touched, validateField]);
// 处理失去焦点事件
const handleBlur = useCallback(() => {
setTouched(true);
const validationError = validateField(value);
setError(validationError);
}, [value, validateField]);
// 手动验证函数(可用于提交前验证)
const validate = useCallback(() => {
setTouched(true);
const validationError = validateField(value);
setError(validationError);
return validationError === ''; // 返回布尔值表示是否有效
}, [value, validateField]);
// 重置字段
const reset = useCallback(() => {
setValue(initialValue);
setError('');
setTouched(false);
}, [initialValue]);
// 返回给组件使用的API
return {
// 状态
value,
error,
touched,
isValid: error === '', // 便捷的有效性检查
// 方法
handleChange,
handleBlur,
validate,
reset,
setValue,
// 便捷的对象展开(用于直接绑定到input)
fieldProps: {
value,
onChange: handleChange,
onBlur: handleBlur,
}
};
};
export default useName;
import React from 'react';
import useField from './useName';
const NameForm = () => {
// 使用自定义Hook
const userName = useField('','userName');
const certNo = useField('','certNo');
const handleSubmit = (e) => {
e.preventDefault();
// 提交前进行最终验证
const isValid = userName.validate();
const isCertNoValid = certNo.validate();
if (isValid && isCertNoValid) {
// 验证通过,处理提交逻辑
alert(`用户名 "${userName.value}" ,身份证号"${certNo.value}"验证通过!`);
} else {
console.log('表单有错误,请检查');
}
};
const handleReset = () =>{
userName.reset();
certNo.reset();
}
return (
<div style={{ maxWidth: '400px', margin: '50px auto', padding: '20px' }}>
<h2>用户验证示例</h2>
<form onSubmit={handleSubmit}>
<div style={{ marginBottom: '20px' }}>
<label htmlFor="userName" style={{ display: 'block', marginBottom: '5px' }}>
用户名:
</label>
<input
type="text"
id="useruserNamename"
// 使用fieldProps便捷绑定
{...userName.fieldProps}
style={{
width: '100%',
padding: '8px',
border: userName.error && userName.touched ? '2px solid red' : '1px solid #ccc',
borderRadius: '4px'
}}
placeholder="请输入用户名"
/>
{/* 错误提示 */}
{user.error && userName.touched && (
<span style={{ color: 'red', fontSize: '14px', marginTop: '5px', display: 'block' }}>
⚠️ {userName.error}
</span>
)}
</div>
<div style={{ marginBottom: '20px' }}>
<label htmlFor="certNo" style={{ display: 'block', marginBottom: '5px' }}>
身份证号:
</label>
<input
type="text"
id="certNo"
// 使用fieldProps便捷绑定
{...certNo.fieldProps}
style={{
width: '100%',
padding: '8px',
border: certNo.error && certNo.touched ? '2px solid red' : '1px solid #ccc',
borderRadius: '4px'
}}
placeholder="请输入身份证号码"
/>
{/* 错误提示 */}
{certNo.error && certNo.touched && (
<span style={{ color: 'red', fontSize: '14px', marginTop: '5px', display: 'block' }}>
⚠️ {certNo.error}
</span>
)}
</div>
<button
type="submit"
style={{
width: '100%',
padding: '10px',
backgroundColor: certNo.isValid ? '#007bff' : '#ccc',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: certNo.isValid ? 'pointer' : 'not-allowed'
}}
disabled={!certNo.isValid}
>
提交
</button>
</form>
{/* 调试信息 */}
<div style={{
marginTop: '30px',
padding: '15px',
backgroundColor: '#f5f5f5',
borderRadius: '4px',
fontSize: '14px'
}}>
<h4>调试信息:</h4>
<p>用户名: <strong>"{userName.value}"</strong></p>
<p>身份证号: <strong>"{certNo.value}"</strong></p>
</div>
{/* 重置按钮 */}
<button
onClick={handleReset}
style={{
marginTop: '10px',
padding: '8px 16px',
backgroundColor: '#6c757d',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer'
}}
>
重置表单
</button>
</div>
);
};
export default NameForm;
console