useValidator
表单验证器
使用方法
首先,需要安装 async-validator
包:
bash
npm install async-validator --save-dev
然后,本地创建 useValidator.ts
文件并写入如下代码:
ts
import Schema, { type Rules, ValidateError, Values, type Rule, ValidateFieldsError } from 'async-validator';
export const useValidator = (
rules: Rules,
data: Record<string, any>
): Promise<{ errors: ValidateError[] | null, fields: ValidateFieldsError | Values }> => {
return new Promise((resolve) => {
const validator = new Schema(rules);
validator.validate(data, (errors, fields) => {
resolve({ errors, fields });
});
})
}
export { Rules, Rule }
使用示例
ts
// 校验规则
const generateRules = (): Rules => {
return {
name: { required: true, message: '请输入名称', transform(value) {return value.trim()} },
age: [{ required: true, message: '请输入年龄' }, { type: 'number', message: '请输入数字'}],
sex: { required: true, type: 'enum', enum: ['男', '女'] }
}
}
// 保存时校验表单
const { errors, fields } = await useValidator(generateRules(), formData.value);
if (errors) {
return ElMessage.error(errors[0].message);
}
参数
参数 | 说明 | 类型 | 默认值 |
---|---|---|---|
rules | 校验规则 | Rules | - |
data | 待校验的数据 | Record<string, any> | - |
返回值
参数 | 说明 | 类型 |
---|---|---|
errors | 返回错误结果 | ValidateError[] | null |
fields | 1. 没有错误时返回处理后的表单数据 2. 有错误时返回错误字段和错误结果 | ValidateFieldsError | Values |
支持校验类型
string
: Must be of typestring
.This is the default type.
number
: Must be of typenumber
.boolean
: Must be of typeboolean
.method
: Must be of typefunction
.regexp
: Must be an instance ofRegExp
or a string that does not generate an exception when creating a newRegExp
.integer
: Must be of typenumber
and an integer.float
: Must be of typenumber
and a floating point number.array
: Must be an array as determined byArray.isArray
.object
: Must be of typeobject
and notArray.isArray
.enum
: Value must exist in theenum
.date
: Value must be valid as determined byDate
url
: Must be of typeurl
.hex
: Must be of typehex
.email
: Must be of typeemail
.any
: Can be any type.
完整规则示例
ts
import Schema from 'async-validator';
// 定义校验规则
const rules = {
// 1. 字符串类型校验(用户名)
username: [
{
type: 'string', // 类型必须为字符串
required: true, // 必填项
message: '用户名不能为空', // 错误提示
},
{
min: 3, // 最小长度 3
max: 10, // 最大长度 10
message: '用户名长度必须在 3-10 个字符之间',
},
{
pattern: /^[a-zA-Z0-9_]+$/, // 只能包含字母、数字、下划线
message: '用户名只能包含字母、数字和下划线',
},
],
// 2. 数字类型校验(年龄)
age: [
{
type: 'number', // 类型必须为数字(注意:字符串数字会被视为无效)
required: true,
message: '年龄不能为空',
},
{
min: 0, // 最小值 0
max: 120, // 最大值 120
message: '年龄必须在 0-120 之间',
},
{
validator(rule, value) {
// 自定义校验:必须为整数
if (!Number.isInteger(value)) {
return Promise.reject('年龄必须为整数');
}
return Promise.resolve();
},
},
],
// 3. 布尔值校验(是否同意协议)
agree: [
{
type: 'boolean',
required: true,
message: '请同意用户协议',
},
{
validator(rule, value) {
// 必须为 true(勾选状态)
if (value !== true) {
return Promise.reject('必须同意用户协议才能继续');
}
return Promise.resolve();
},
},
],
// 4. 数组校验(爱好列表)
hobbies: [
{
type: 'array',
required: true,
message: '至少选择一个爱好',
},
{
min: 1, // 至少选择 1 项
max: 3, // 最多选择 3 项
message: '爱好选择数量必须在 1-3 之间',
},
{
validator(rule, value) {
// 自定义校验:必须包含指定选项(如 'reading')
if (!value.includes('reading')) {
return Promise.reject('爱好必须包含阅读');
}
return Promise.resolve();
},
},
],
// 5. 对象校验(地址信息)
address: [
{
type: 'object',
required: true,
message: '地址信息不能为空',
},
{
// 嵌套对象校验
fields: {
city: [
{ type: 'string', required: true, message: '城市不能为空' },
],
street: [
{ type: 'string', required: true, message: '街道不能为空' },
{ min: 5, message: '街道名称至少 5 个字符' },
],
zipCode: [
{ type: 'string', required: true, message: '邮编不能为空' },
{ pattern: /^\d{6}$/, message: '邮编必须是 6 位数字' },
],
},
},
],
// 6. 邮箱格式校验
email: [
{
type: 'email', // 内置邮箱格式校验
required: true,
message: '请输入有效的邮箱地址',
},
],
// 7. 自定义异步校验(模拟后端校验用户名是否已存在)
nickname: [
{
type: 'string',
required: true,
message: '昵称不能为空',
},
{
async validator(rule, value) {
// 模拟异步请求(如调用后端接口)
return new Promise((resolve, reject) => {
setTimeout(() => {
const existNicknames = ['admin', 'root', 'guest'];
if (existNicknames.includes(value)) {
reject('该昵称已被占用,请更换');
} else {
resolve();
}
}, 500); // 模拟网络延迟
});
},
},
],
// 8. 枚举值校验(性别)
gender: [
{
type: 'enum',
enum: ['male', 'female', 'other'], // 只能是指定值
required: true,
message: '请选择性别',
},
],
// 9. 日期格式校验
birthday: [
{
type: 'date', // 支持 Date 对象或 ISO 格式字符串(如 '2020-01-01')
required: true,
message: '请输入有效的出生日期',
},
{
validator(rule, value) {
// 出生日期不能晚于当前时间
const now = new Date();
if (new Date(value) > now) {
return Promise.reject('出生日期不能晚于当前时间');
}
return Promise.resolve();
},
},
],
};