async-validator
async-validator是一個(gè)表單的異步驗(yàn)證的第三方庫(kù)许起,它是 https://github.com/tmpfs/async-validate 的演變册着。也是element-ui 中的form組件所使用的驗(yàn)證方式检吆。
API
注意:以下內(nèi)容是從早期版本的異步驗(yàn)證修改而來(lái)的跪削。
install
npm install --save async-validator
使用
基本用法包括定義一個(gè)descriptor挖胃,將其分配給schema双泪,并將要驗(yàn)證的對(duì)象和回調(diào)函數(shù)傳遞給schema創(chuàng)建出來(lái)的validator的validate方法:
// 基本用法
var schema = require('async-validator'); // 引用組件
var descriptor = {
name: {
type: "string",
required: true,
validator: (rule, value) => value === 'muji',
}
}; // 定義一個(gè)descriptor
var validator = new schema(descriptor); // descriptor分配給schema,創(chuàng)建一個(gè)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
}); // 參數(shù)一:要驗(yàn)證的對(duì)象吉殃、參數(shù)二:回調(diào)函數(shù)
// 使用 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
: 要驗(yàn)證的對(duì)象(必需) -
options
: 描述驗(yàn)證處理選項(xiàng)的對(duì)象(可選) -
callback
: 驗(yàn)證完成時(shí)調(diào)用的回調(diào)函數(shù)(必需)
該方法將返回Promise對(duì)象辞居,如:
-
then()
: 驗(yàn)證通過(guò) -
catch({ errors, fields })
: 驗(yàn)證失敗,errors是一個(gè)包含所有錯(cuò)誤的數(shù)組蛋勺,fields 是由字段名稱做鍵值對(duì)的對(duì)象所組成的數(shù)組瓦灶。
Options
-
suppressWarning
: Boolean,是否禁止有關(guān)無(wú)效值的內(nèi)部警告抱完。 -
first
: Boolean贼陶,當(dāng)?shù)谝粋€(gè)驗(yàn)證規(guī)則生成錯(cuò)誤時(shí)調(diào)用回調(diào),不再處理其他驗(yàn)證規(guī)則。如果驗(yàn)證涉及多個(gè)異步調(diào)用(例如數(shù)據(jù)庫(kù)查詢)碉怔,并且只需要第一個(gè)錯(cuò)誤烘贴,請(qǐng)使用此選項(xiàng)。 -
firstFields
: Boolean|String[],當(dāng)指定字段的第一個(gè)驗(yàn)證規(guī)則生成錯(cuò)誤時(shí)調(diào)用回調(diào)撮胧,不處理同一字段的其他驗(yàn)證規(guī)則桨踪。“真”表示所有字段趴樱。
Rules
Rules可以是執(zhí)行驗(yàn)證的函數(shù)馒闷,例如上面:var descriptor = { name: {} }中的
name
,不僅僅是一個(gè)對(duì)象叁征,還可以是一個(gè)函數(shù)纳账。相關(guān)如下:
function(rule, value, callback, source, options)
-
rule
: 源描述符中與要驗(yàn)證的字段名相對(duì)應(yīng)的驗(yàn)證規(guī)則。它始終被分配一個(gè)字段屬性捺疼,該屬性具有要驗(yàn)證的字段的名稱疏虫。 -
value
: 正在驗(yàn)證的源對(duì)象屬性的值。 -
callback
: 驗(yàn)證完成后調(diào)用的回調(diào)函數(shù)啤呼。它需要傳遞一個(gè)錯(cuò)誤實(shí)例數(shù)組來(lái)指示驗(yàn)證失敗卧秘。如果檢查是同步的,則可以直接返回一個(gè)錯(cuò)誤官扣、錯(cuò)誤或錯(cuò)誤數(shù)組翅敌。 -
source
: 傳遞給validate方法的源對(duì)象。 -
options
: 附加選項(xiàng)惕蹄。 -
options.messages
: 包含驗(yàn)證錯(cuò)誤消息的對(duì)象將與defaultmessages深度合并蚯涮。
傳遞給validate或asyncvalidate的選項(xiàng)將傳遞給驗(yàn)證函數(shù),以便您可以在驗(yàn)證函數(shù)中臨時(shí)引用數(shù)據(jù)(例如模型引用)卖陵。但是遭顶,某些選項(xiàng)名是保留的;如果使用選項(xiàng)對(duì)象的這些屬性泪蔫,它們將被覆蓋棒旗。保留的屬性是消息、異常和錯(cuò)誤撩荣。
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
});
針對(duì)單個(gè)字段測(cè)試多個(gè)驗(yàn)證規(guī)則通常很有用铣揉,這樣可以使規(guī)則成為對(duì)象數(shù)組,例如:
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;
}
}
]
}
規(guī)則的參數(shù)
type
要使用的驗(yàn)證程序的類(lèi)型婿滓,識(shí)別的類(lèi)型值如下:
-
string
: 必須是 String 類(lèi)型老速。這是默認(rèn)類(lèi)型。 -
number
: 必須是 Number 類(lèi)型凸主。 -
boolean
: 必須是 Boolean 類(lèi)型。 -
method
: 必須是 Function 類(lèi)型额湘。 -
regexp
: 必須是 RegExp 的實(shí)例或在創(chuàng)建新 RegExp 時(shí)不生成異常的字符串卿吐。 -
integer
: 必須是 Number 和整數(shù)類(lèi)型旁舰。 -
float
: 必須是 Number 和浮點(diǎn)數(shù)類(lèi)型。 -
array
: 必須是由array.isarray確定的數(shù)組嗡官。 -
object
: 必須是 Object 類(lèi)型箭窜,而不是Array.IsArray類(lèi)型。 -
enum
: 值必須存在于枚舉中衍腥。 -
date
: 必須是 Date 類(lèi)型磺樱。 -
url
: 必須是url類(lèi)型。 -
hex
: 必須是十六進(jìn)制類(lèi)型婆咸。 -
email
: 必須是電子郵件類(lèi)型竹捉。
Required
boolean,是否必填
Pattern:
模式規(guī)則屬性表示正則表達(dá)式,該值必須匹配才能通過(guò)驗(yàn)證。
Range:
使用min和max屬性定義范圍尚骄。對(duì)于字符串和數(shù)組類(lèi)型块差,將根據(jù)長(zhǎng)度進(jìn)行比較,對(duì)于數(shù)字類(lèi)型倔丈,數(shù)字不得小于min憨闰,也不得大于max。
Length:
驗(yàn)證字段的確切長(zhǎng)度需五。對(duì)于字符串和數(shù)組類(lèi)型鹉动,對(duì)length屬性執(zhí)行比較,對(duì)于數(shù)字類(lèi)型宏邮,此屬性指示數(shù)字的完全匹配泽示,即,它可能僅嚴(yán)格等于len蜀铲。如果len屬性與最小和最大范圍屬性組合边琉,則len優(yōu)先。
Enumerable:
枚舉记劝,要從可能值列表中驗(yàn)證值变姨,請(qǐng)使用帶有枚舉屬性的枚舉類(lèi)型,列出該字段的有效值厌丑。
var descriptor = {
role: { type: "enum", enum: ['admin', 'user', 'guest'] }
}
Whitespace:
空白定欧,通常將僅包含空格的必填字段視為錯(cuò)誤。要為僅包含空格的字符串添加其他測(cè)試怒竿,請(qǐng)將空白屬性添加到值為true的規(guī)則砍鸠。規(guī)則必須是字符串類(lèi)型。
Deep Rules:
如果需要驗(yàn)證深層對(duì)象屬性耕驰,則可以通過(guò)將嵌套規(guī)則分配給規(guī)則的fields屬性來(lái)為對(duì)象或數(shù)組類(lèi)型的驗(yàn)證規(guī)則執(zhí)行此操作爷辱。
// 深度規(guī)則
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
});
注意:如果您沒(méi)有在父規(guī)則上指定必需的屬性,那么對(duì)于不在源對(duì)象上聲明的字段是完全有效的,并且不會(huì)執(zhí)行深度驗(yàn)證規(guī)則饭弓,因?yàn)闆](méi)有要驗(yàn)證的內(nèi)容双饥。
深度規(guī)則驗(yàn)證為嵌套規(guī)則創(chuàng)建架構(gòu),因此還可以指定傳遞給schema.validate()方法的選項(xiàng)弟断。
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
});
父規(guī)則也會(huì)被驗(yàn)證咏花,因此如果您有一組規(guī)則,例如:
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"]}
這樣的源對(duì)象阀趴,將會(huì)創(chuàng)建兩個(gè)錯(cuò)誤昏翰。一個(gè)用于數(shù)組長(zhǎng)度不匹配,另一個(gè)用于索引2處缺少的必需數(shù)組項(xiàng)刘急。
defaultField:
defaultField屬性可與數(shù)組或?qū)ο箢?lèi)型一起使用棚菊,以驗(yàn)證容器的所有值。它可以是包含驗(yàn)證規(guī)則的對(duì)象或數(shù)組排霉。例如:
var descriptor = {
urls: {
type: "array", required: true,
defaultField: {type: "url"}
}
}
Transform:
有時(shí)需要在驗(yàn)證之前轉(zhuǎn)換值窍株,可能是為了強(qiáng)制價(jià)值或以某種方式對(duì)其進(jìn)行消毒。為此攻柠,請(qǐng)將驗(yàn)證規(guī)則添加到轉(zhuǎn)換有時(shí)需要在驗(yàn)證之前轉(zhuǎn)換一個(gè)值球订,可能是強(qiáng)制值或以某種方式對(duì)其進(jìn)行清理。為此瑰钮,請(qǐng)向驗(yàn)證規(guī)則添加轉(zhuǎn)換函數(shù)冒滩。該屬性在驗(yàn)證之前被轉(zhuǎn)換,并重新分配給源對(duì)象浪谴,以在適當(dāng)?shù)奈恢酶淖冊(cè)搶傩缘闹怠?/p>
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"));
如果沒(méi)有轉(zhuǎn)換函數(shù)开睡,驗(yàn)證將失敗,因?yàn)槟J讲黄ヅ涔冻埽驗(yàn)檩斎氚皩?dǎo)空格和尾隨空格篇恒,但通過(guò)添加轉(zhuǎn)換函數(shù)驗(yàn)證傳遞,同時(shí)清理字段值凶杖。
Messages:
消息胁艰,根據(jù)您的應(yīng)用程序要求,您可能需要i18n支持智蝠,或者您可能更喜歡不同的驗(yàn)證錯(cuò)誤消息腾么。實(shí)現(xiàn)這一點(diǎn)的最簡(jiǎn)單方法是將消息分配給規(guī)則:
{name:{type: "string", required: true, message: "Name is required"}}
消息可以是任何類(lèi)型,例如jsx格式杈湾。
{name:{type: "string", required: true, message: <b>Name is required</b>}}
消息也可以是一個(gè)函數(shù)解虱,例如,如果使用vue-i18n:
{name:{type: "string", required: true, message: () => this.$t( 'name is required' )}}
對(duì)于不同的語(yǔ)言漆撞,可能需要相同的模式驗(yàn)證規(guī)則殴泰,在這種情況下于宙,為每種語(yǔ)言復(fù)制模式規(guī)則是沒(méi)有意義的。在這個(gè)場(chǎng)景中艰匙,您只需為該語(yǔ)言提供您自己的消息并將其分配給模式:
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);
// ...
如果要定義自己的驗(yàn)證函數(shù)限煞,最好將消息字符串分配給消息對(duì)象抹恳,然后通過(guò)驗(yàn)證函數(shù)內(nèi)的options.messages屬性訪問(wèn)消息员凝。
asyncValidator
異步驗(yàn)證器,您可以為指定字段自定義異步驗(yàn)證函數(shù):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:
驗(yàn)證器奋献,您可以為指定字段自定義驗(yàn)證函數(shù):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'),
];
}
},
};
常見(jiàn)問(wèn)題
如何避免警告
var Schema = require('async-validator');
Schema.warning = function(){};