表单异步验证js库:async-validator

async-validator

async-validator是一个表单的异步验证的第三方库,它是 https://github.com/tmpfs/async-validate 的演变。也是element-ui 中的form组件所使用的验证方式。

API

注意:以下内容是从早期版本的异步验证修改而来的。

install

npm install --save async-validator

使用

基本用法包括定义一个descriptor,将其分配给schema,并将要验证的对象和回调函数传递给schema创建出来的validator的validate方法:

// 基本用法
var schema = require('async-validator'); // 引用组件
var descriptor = {
 name: {
  type: "string",
  required: true,
  validator: (rule, value) => value === 'muji',
 }
}; // 定义一个descriptor
var validator = new schema(descriptor); // descriptor分配给schema,创建一个validator
validator.validate({name: "muji"}, (errors, fields) => {
 if(errors) {
  // validation failed, errors is an array of all errors
  // fields is an object keyed by field name with an array of
  // errors per field
 return handleErrors(errors, fields);
 }
  // validation passed
}); // 参数一:要验证的对象、参数二:回调函数

// 使用 promise
validator.validate({
  name: "muji",
 asyncValidator: (rule, value) => axios.post('/nameValidator', { name: value }),
}, (errors, fields) => {
 if(errors) {
  // validation failed, errors is an array of all errors
  // fields is an object keyed by field name with an array of
  // errors per field
 return handleErrors(errors, fields);
 }
  // validation passed
})
.then(() => {
  // validation passed
})
.catch(({ errors, fields }) => {
 return handleErrors(errors, fields);
})

Validate


function(source, [options], callback): Promise

  • source: 要验证的对象(必需)
  • options: 描述验证处理选项的对象(可选)
  • callback: 验证完成时调用的回调函数(必需)

该方法将返回Promise对象,如:

  • then(): 验证通过
  • catch({ errors, fields }): 验证失败,errors是一个包含所有错误的数组,fields 是由字段名称做键值对的对象所组成的数组。

Options

  • suppressWarning: Boolean,是否禁止有关无效值的内部警告。
  • first: Boolean,当第一个验证规则生成错误时调用回调,不再处理其他验证规则。如果验证涉及多个异步调用(例如数据库查询),并且只需要第一个错误,请使用此选项。
  • firstFields: Boolean|String[],当指定字段的第一个验证规则生成错误时调用回调,不处理同一字段的其他验证规则。“真”表示所有字段。

Rules

Rules可以是执行验证的函数,例如上面:var descriptor = { name: {} }中的name,不仅仅是一个对象,还可以是一个函数。相关如下:

function(rule, value, callback, source, options)
  • rule: 源描述符中与要验证的字段名相对应的验证规则。它始终被分配一个字段属性,该属性具有要验证的字段的名称。
  • value: 正在验证的源对象属性的值。
  • callback: 验证完成后调用的回调函数。它需要传递一个错误实例数组来指示验证失败。如果检查是同步的,则可以直接返回一个错误、错误或错误数组。
  • source: 传递给validate方法的源对象。
  • options: 附加选项。
  • options.messages: 包含验证错误消息的对象将与defaultmessages深度合并。

传递给validate或asyncvalidate的选项将传递给验证函数,以便您可以在验证函数中临时引用数据(例如模型引用)。但是,某些选项名是保留的;如果使用选项对象的这些属性,它们将被覆盖。保留的属性是消息、异常和错误。

var schema = require('async-validator');
var descriptor = {
 name(rule, value, callback, source, options) {
 var errors = [];
 if(!/^[a-z0-9]+$/.test(value)) {
 errors.push(
 new Error(
 util.format("%s must be lowercase alphanumeric characters",
 rule.field)));
 }
 return errors;
 }
}
var validator = new schema(descriptor);
validator.validate({name: "Firstname"}, (errors, fields) => {
 if(errors) {
 return handleErrors(errors, fields);
 }
  // validation passed
});

针对单个字段测试多个验证规则通常很有用,这样可以使规则成为对象数组,例如:

var descriptor = {
 email: [
 { type: "string", required: true, pattern: schema.pattern.email },
 {
 validator (rule, value, callback, source, options) {
 var errors = [];
  // test if email address already exists in a database
  // and add a validation error to the errors array if it does
 return errors;
 }
 }
 ]
}

规则的参数

type

要使用的验证程序的类型,识别的类型值如下:

  • string: 必须是 String 类型。这是默认类型。
  • number: 必须是 Number 类型。
  • boolean: 必须是 Boolean 类型。
  • method: 必须是 Function 类型。
  • regexp: 必须是 RegExp 的实例或在创建新 RegExp 时不生成异常的字符串。
  • integer: 必须是 Number 和整数类型。
  • float: 必须是 Number 和浮点数类型。
  • array: 必须是由array.isarray确定的数组。
  • object: 必须是 Object 类型,而不是Array.IsArray类型。
  • enum: 值必须存在于枚举中。
  • date: 必须是 Date 类型。
  • url: 必须是url类型。
  • hex: 必须是十六进制类型。
  • email: 必须是电子邮件类型。
Required

boolean,是否必填

Pattern:

模式规则属性表示正则表达式,该值必须匹配才能通过验证。

Range:

使用min和max属性定义范围。对于字符串和数组类型,将根据长度进行比较,对于数字类型,数字不得小于min,也不得大于max。

Length:

验证字段的确切长度。对于字符串和数组类型,对length属性执行比较,对于数字类型,此属性指示数字的完全匹配,即,它可能仅严格等于len。如果len属性与最小和最大范围属性组合,则len优先。

Enumerable:

枚举,要从可能值列表中验证值,请使用带有枚举属性的枚举类型,列出该字段的有效值。

var descriptor = {
 role: { type: "enum", enum: ['admin', 'user', 'guest'] }
}
Whitespace:

空白,通常将仅包含空格的必填字段视为错误。要为仅包含空格的字符串添加其他测试,请将空白属性添加到值为true的规则。规则必须是字符串类型。

Deep Rules:

如果需要验证深层对象属性,则可以通过将嵌套规则分配给规则的fields属性来为对象或数组类型的验证规则执行此操作。

// 深度规则
var 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}
}
var validator = new schema(descriptor);
validator.validate({ address: {} }, (errors, fields) => {
  // errors for address.street, address.city, address.zip
});

注意:如果您没有在父规则上指定必需的属性,那么对于不在源对象上声明的字段是完全有效的,并且不会执行深度验证规则,因为没有要验证的内容。

深度规则验证为嵌套规则创建架构,因此还可以指定传递给schema.validate()方法的选项。

var descriptor = {
 address: {
 type: "object", required: true, options: {single: true, first: 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}
}
var validator = new schema(descriptor);
validator.validate({ address: {} }).catch(({ errors, fields }) => {
// now only errors for street and name    
});

父规则也会被验证,因此如果您有一组规则,例如:

var descriptor = {
 roles: {
 type: "array", required: true, len: 3,
 fields: {
 0: {type: "string", required: true},
 1: {type: "string", required: true},
 2: {type: "string", required: true}
 }
 }
}

并提供 {roles: ["admin", "user"]} 这样的源对象,将会创建两个错误。一个用于数组长度不匹配,另一个用于索引2处缺少的必需数组项。

defaultField:

defaultField属性可与数组或对象类型一起使用,以验证容器的所有值。它可以是包含验证规则的对象或数组。例如:

var descriptor = {
 urls: {
 type: "array", required: true,
 defaultField: {type: "url"}
 }
}
Transform:

有时需要在验证之前转换值,可能是为了强制价值或以某种方式对其进行消毒。为此,请将验证规则添加到转换有时需要在验证之前转换一个值,可能是强制值或以某种方式对其进行清理。为此,请向验证规则添加转换函数。该属性在验证之前被转换,并重新分配给源对象,以在适当的位置改变该属性的值。

var schema = require('async-validator');
var sanitize = require('validator').sanitize;
var descriptor = {
 name: {
  type: "string",
 required: true, pattern: /^[a-z]+$/,
 transform(value) {
 return sanitize(value).trim();
 }
 }
}
var validator = new schema(descriptor);
var  source = {name: " user "};
validator.validate(source).then(() => assert.equal(source.name, "user"));

如果没有转换函数,验证将失败,因为模式不匹配,因为输入包含前导空格和尾随空格,但通过添加转换函数验证传递,同时清理字段值。

Messages:

消息,根据您的应用程序要求,您可能需要i18n支持,或者您可能更喜欢不同的验证错误消息。实现这一点的最简单方法是将消息分配给规则:

{name:{type: "string", required: true, message: "Name is required"}}

消息可以是任何类型,例如jsx格式。

{name:{type: "string", required: true, message: <b>Name is required</b>}}

消息也可以是一个函数,例如,如果使用vue-i18n:

{name:{type: "string", required: true, message: () => this.$t( 'name is required' )}}

对于不同的语言,可能需要相同的模式验证规则,在这种情况下,为每种语言复制模式规则是没有意义的。在这个场景中,您只需为该语言提供您自己的消息并将其分配给模式:

var schema = require('async-validator');
var cn = {
 required: '%s 必填',
};
var descriptor = {name:{type: "string", required: true}};
var validator = new schema(descriptor);
// deep merge with defaultMessages
validator.messages(cn);
// ...

如果要定义自己的验证函数,最好将消息字符串分配给消息对象,然后通过验证函数内的options.messages属性访问消息。

asyncValidator

异步验证器,您可以为指定字段自定义异步验证函数:function(rule, value, callback)

const fields = {
 asyncField:{
 asyncValidator(rule,value,callback){
 ajax({
 url:'xx',
  value:value
 }).then(function(data){
 callback();
 },function(error){
 callback(new Error(error))
 });
 }
 },
 promiseField:{
 asyncValidator(rule, value){
 return ajax({
 url:'xx',
  value:value
 });
 }
 }
};
validator:

验证器,您可以为指定字段自定义验证函数:function(rule, value, callback)

const fields = {
 field:{
 validator(rule,value,callback){
 return value === 'test';
 },
 message: 'Value is not equal to "test".',
 },
 field2:{
 validator(rule,value,callback){
  return  new Error(`'${value} is not equal to "test".'`);
 },
 },
 arrField:{
 validator(rule, value){
 return [
 new Error('Message 1'),
 new Error('Message 2'),
 ];
 }
 },
};

常见问题

如何避免警告

var Schema = require('async-validator');
Schema.warning = function(){};
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342