表單異步驗(yàn)證js庫(kù):async-validator

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(){};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末健霹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子瓶蚂,更是在濱河造成了極大的恐慌糖埋,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件窃这,死亡現(xiàn)場(chǎng)離奇詭異瞳别,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)杭攻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門(mén)祟敛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人兆解,你說(shuō)我怎么就攤上這事馆铁。” “怎么了锅睛?”我有些...
    開(kāi)封第一講書(shū)人閱讀 167,834評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵埠巨,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我现拒,道長(zhǎng)辣垒,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,543評(píng)論 1 296
  • 正文 為了忘掉前任印蔬,我火速辦了婚禮勋桶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扛点。我一直安慰自己哥遮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布陵究。 她就那樣靜靜地躺著眠饮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铜邮。 梳的紋絲不亂的頭發(fā)上仪召,一...
    開(kāi)封第一講書(shū)人閱讀 52,196評(píng)論 1 308
  • 那天寨蹋,我揣著相機(jī)與錄音,去河邊找鬼扔茅。 笑死已旧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的召娜。 我是一名探鬼主播运褪,決...
    沈念sama閱讀 40,776評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼玖瘸!你這毒婦竟也來(lái)了秸讹?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,671評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤雅倒,失蹤者是張志新(化名)和其女友劉穎璃诀,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蔑匣,經(jīng)...
    沈念sama閱讀 46,221評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡劣欢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了裁良。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片凿将。...
    茶點(diǎn)故事閱讀 40,444評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖趴久,靈堂內(nèi)的尸體忽然破棺而出丸相,到底是詐尸還是另有隱情,我是刑警寧澤彼棍,帶...
    沈念sama閱讀 36,134評(píng)論 5 350
  • 正文 年R本政府宣布灭忠,位于F島的核電站,受9級(jí)特大地震影響座硕,放射性物質(zhì)發(fā)生泄漏弛作。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評(píng)論 3 333
  • 文/蒙蒙 一华匾、第九天 我趴在偏房一處隱蔽的房頂上張望映琳。 院中可真熱鬧,春花似錦蜘拉、人聲如沸萨西。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,285評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)谎脯。三九已至,卻和暖如春持寄,著一層夾襖步出監(jiān)牢的瞬間源梭,已是汗流浹背娱俺。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,399評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留废麻,地道東北人荠卷。 一個(gè)月前我還...
    沈念sama閱讀 48,837評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像烛愧,于是被迫代替她去往敵國(guó)和親油宜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評(píng)論 2 359