validate form asynchronous
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 4 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 11 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 6 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 9 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 4 年前 | ||
| 4 年前 |
异步验证器
异步表单验证。基于 https://github.com/freeformsystems/async-validate 的一个变体。
安装
npm i async-validator
使用
基本使用包括定义描述符,将其分配给模式,并将要验证的对象和回调函数传递给模式的validate方法:
import Schema from 'async-validator';
const descriptor = {
name: {
type: 'string',
required: true,
validator: (rule, value) => value === 'muji',
},
age: {
type: 'number',
asyncValidator: (rule, value) => {
return new Promise((resolve, reject) => {
if (value < 18) {
reject('too young'); // 拒绝并返回错误信息
} else {
resolve();
}
});
},
},
};
const validator = new Schema(descriptor);
validator.validate({ name: 'muji' }, (errors, fields) => {
if (errors) {
// 验证失败,errors 是所有错误的数组
// fields 是按字段名键值对存储的错误对象
return handleErrors(errors, fields);
}
// 验证通过
});
// 用法 - 承诺
validator.validate({ name: 'muji', age: 16 }).then(() => {
// 验证通过或者没有错误消息
}).catch(({ errors, fields }) => {
return handleErrors(errors, fields);
});
API
验证
function(source, [options], callback): Promise
source: 要验证的对象(必需)。options: 描述验证处理选项的对象(可选)。callback: 验证完成时调用的回调函数(可选)。
该方法会返回一个Promise对象:
then(),验证成功catch({ errors, fields }),验证失败,errors是所有错误的数组,fields是按字段名键值对存储的每个字段的错误数组
选项
-
suppressWarning: 布尔值,是否抑制内部关于无效值的警告。 -
first: 布尔值,当第一个验证规则产生错误时调用callback,不再处理其他规则。如果您的验证涉及多个异步调用(例如数据库查询),并且只需要第一个错误,则可以使用此选项。 -
firstFields: 布尔值 | 字符串数组,当指定字段的第一个验证规则产生错误时调用callback,不再处理同一字段的其他规则。true表示所有字段。
规则
规则可以是执行验证的函数。
function(rule, value, callback, source, options)
rule: 在源描述符中对应于正在验证的字段名称的验证规则。它总是有一个名为field的属性,包含正在验证的字段的名称。value: 正在验证的源对象属性的值。callback: 验证完成后调用的函数。期望接收一个表示验证失败的Error实例数组。如果检查是同步的,您可以直接返回false、Error或Error数组。source: 传递给validate方法的源对象。options: 其他选项。options.messages: 含有验证错误消息的对象,将与defaultMessages深度合并。
传递给validate或asyncValidate的选项将传递给验证函数,以便您可以在验证函数中引用临时数据(如模型引用)。但是,某些选项名称是保留的;如果你使用这些选项对象的属性,它们会被覆盖。保留的属性有messages、exception和error。
import Schema from 'async-validator';
const descriptor = {
name(rule, value, callback, source, options) {
const errors = [];
if (!/^[a-z0-9]+$/.test(value)) {
errors.push(new Error(
util.format('%s 必须是小写字母数字字符', rule.field),
));
}
return errors;
},
};
const validator = new Schema(descriptor);
validator.validate({ name: 'Firstname' }, (errors, fields) => {
if (errors) {
return handleErrors(errors, fields);
}
// 验证通过
});
经常需要针对单个字段测试多个验证规则,为此,使规则成为一个包含对象的数组,例如:
const descriptor = {
email: [
{ type: 'string', required: true, pattern: Schema.pattern.email },
{
validator(rule, value, callback, source, options) {
const errors = [];
// 测试电子邮件地址是否已存在于数据库中
// 如果存在,则向错误数组添加一个验证错误
return errors;
},
},
],
};
类型
指示要使用的验证器类型。认可的类型值有:
string: 必须是字符串类型。这是默认类型。number: 必须是数字类型。boolean: 必须是布尔类型。method: 必须是函数类型。regexp: 必须是RegExp实例或创建新RegExp时不会抛出异常的字符串。integer: 必须是数字类型且为整数。float: 必须是数字类型且为浮点数。array: 必须通过Array.isArray确定为数组。object: 必须是类型为object而不是Array.isArray的对象。enum: 值必须存在于枚举中。date: 值必须是有效的日期。url: 必须是URL类型。hex: 必须是十六进制类型。email: 必须是电子邮件类型。any: 可以是任何类型。
必需
required规则属性表明验证的源对象上必须存在该字段。
模式
pattern规则属性指示值必须匹配的正则表达式才能通过验证。
范围
范围使用min和max属性定义。对于string和array类型,比较是在length上进行的,对于number类型,数字不能小于min或大于max。
长度
要验证字段的确切长度,指定len属性。对于string和array类型,比较的是length属性,对于number类型,该属性表示与len严格相等。
如果len属性与min和max范围属性结合使用,len优先。
枚举
自从版本3.0.0,如果您想在
enum类型中验证值0或false,您必须明确地包含它们。
要从可能的值列表中验证值,使用enum类型并将有效的字段值列表赋给enum属性,例如:
const descriptor = {
role: { type: 'enum', enum: ['admin', 'user', 'guest'] },
};
空白
通常认为只含有空白的必要字段是错误的。要在规则中添加一个额外的测试以检测仅由空格组成的字符串,将whitespace属性设置为true。该规则必须是string类型。
您可能希望清理用户输入,而不是测试空白,参阅transform示例,该示例允许您删除空白。
深度规则
如果需要验证深层对象属性,可以通过将嵌套规则分配给规则的fields属性来为object或array类型的规则执行此操作。
const descriptor = {
address: {
type: 'object',
required: true,
fields: {
street: { type: 'string', required: true },
city: { type: 'string', required: true },
zip: { type: 'string', required: true, len: 8, message: 'invalid zip' },
},
},
name: { type: 'string', required: true },
};
const validator = new Schema(descriptor);
validator.validate({ address: {} }, (errors, fields) => {
// 地址.street、地址.city、地址.zip 的错误
});
请注意,如果不为父规则指定required属性,那么即使字段没有在源对象上声明,也是完全合法的,因为没有什么要验证的,所以深层验证规则不会执行。
深度规则验证会为嵌套规则创建一个架构,因此您也可以指定传递给schema.validate()方法的options。
const schemaDescriptor = {
address: {
type: 'object',
presence: true,
priority: true,
fields: {
street: { type: 'string', presence: true },
city: { type: 'string', presence: true },
zip: {
type: 'string',
presence: true,
length: { exactly: 8 },
errorMessage: 'invalid zip code',
},
},
},
name: { type: 'string', presence: true },
};
const schemaValidator = new Schema(schemaDescriptor);
schemaValidator.validate({ address: {} })
.catch(({ errors, invalidFields }) => {
// At this point, errors only concern the 'street' and 'name'
});
当规则如以下所示时,父级规则也会被验证:
const roleDescriptor = {
roles: {
type: 'array',
presence: true,
length: { exactly: 3 },
fields: {
0: { type: 'string', presence: true },
1: { type: 'string', presence: true },
2: { type: 'string', presence: true },
},
},
};
// 假设提供的数据是 { roles: ['admin', 'user'] }
// 那么会生成两个错误:一个是因为数组长度不符,另一个是因为索引为2的必需数组条目缺失
默认字段(defaultField)
defaultField 属性可用于 array 或 object 类型,以对容器中的所有值进行验证。它可以是一个包含验证规则的 object 或 array,例如:
const descriptor = {
urls: {
type: 'array',
presence: true,
defaultField: { type: 'url' },
},
};
请注意,defaultField 将扩展为 fields,详情见深度规则部分。
转换(Transform)
有时在验证之前需要转换值,可能是为了强制类型转换,或者以某种方式清理值。为此,在验证规则中添加一个 transform 函数。属性在验证前进行转换,并作为通过验证后的承诺结果或回调结果返回。
import Schema from 'async-validator';
const descriptor = {
name: {
type: 'string',
presence: true,
pattern: /^[a-z]+$/,
transform(value) {
return value.trim();
},
},
};
const validator = new Schema(descriptor);
const dataSource = { name: ' user ' };
validator.validate(dataSource)
.then((data) => assert.equal(data.name, 'user'));
validator.validate(dataSource, (errors, data) => {
assert.equal(data.name, 'user'));
});
如果没有 transform 函数,由于输入带有前后空格,模式匹配会失败,但通过添加这个转换函数,验证成功并且字段值得到了清理。
消息(Messages)
根据应用程序需求,您可能需要国际化支持,或者希望使用不同的验证错误消息。
最简单的方法是在规则上分配一个 message:
{ name: { type: 'string', presence: true, message: 'Name is required' } }
消息可以是任意类型,比如 JSX 格式:
{ name: { type: 'string', presence: true, message: '<b>Name is required</b>' } }
消息也可以是一个函数,例如,如果你使用 vue-i18n:
{ name: { type: 'string', presence: true, message: () => this.$t('name is required') } }
可能有些情况下,你需要用不同的语言对相同的 schema 规则进行验证,直接为每种语言复制 schema 规则并不合理。
在这种情况下,你可以为指定的语言提供自己的消息,并将其分配给 schema:
import Schema from 'async-validator';
const chineseMessages = {
presence: '%s 是必填项',
};
const descriptor = { name: { type: 'string', presence: true } };
const validator = new Schema(descriptor);
// 合并到默认消息
validator.messages(chineseMessages);
...
如果你定义了自己的验证函数,最好实践是在消息对象中分配消息字符串,然后在验证函数内部通过 options.messages 属性访问这些消息。
自定义异步验证器(asyncValidator)
可以为指定字段自定义异步验证函数:
const fields = {
asyncField: {
asyncValidator: (rule, value, callback) => {
ajax({
url: 'xx',
value: value,
}).then(callback, (error) => callback(new Error(error)));
},
},
promiseField: {
asyncValidator: (rule, value) =>
ajax({
url: 'xx',
value: value,
}),
},
};
自定义验证器(validator)
可以为特定字段定制验证函数:
const fields = {
field: {
validator: (rule, value, callback) => callback(value === 'test'),
errorMessage: 'Value does not equal "test".',
},
field2: {
validator: (rule, value, callback) => callback(new Error(`${value} is not equal to 'test'.`)),
},
arrField: {
validator: (rule, value) => [
new Error('Message 1'),
new Error('Message 2'),
],
},
};
经常问的问题(FAQ)
如何避免全局警告
import Schema from 'async-validator';
Schema.warning = () => {};
或者
globalThis.ASYNC_VALIDATOR_NO_WARNING = 1;
如何检查是否为 true
使用 enum 类型,将选项设置为 true:
{
type: 'enum',
enum: [true],
errorMessage: '',
}
测试案例
npm test
代码覆盖率
npm run coverage
打开 coverage/ 目录
许可证
一切都是 MIT 许可证。