深入掌握ant-design的form異步校驗(yàn)(一)
一、前言
本文基于開源項(xiàng)目:
https://github1s.com/ant-design/ant-design
https://github.com/yiminghe/async-validator
很多小伙伴對(duì)antd的form表單校驗(yàn)不是很清楚,有些時(shí)候?qū)懥艘恍┬r?yàn)規(guī)則然后不是自己想要實(shí)現(xiàn)的效果、或者不清楚校驗(yàn)規(guī)則是什么無從寫起。
下面我們一起來學(xué)習(xí)學(xué)習(xí)form的校驗(yàn)~
二、validateFields
廣東靚仔從文檔找了個(gè)demo,代碼如下:
<Form form={form} initialValues={{ aaa: '2' }}>
<Form.Item name="aaa">
<Input
onChange={async () => {
await sleep(0);
try {
await form.validateFields();
} catch (e) {
// do nothing
}
}}
/>
</Form.Item>
<Form>
我們來看看validateFields的返回示例:
validateFields()
.then(values => {
/*
values:
{
username: 'username',
password: 'password',
}
*/
})
.catch(errorInfo => {
/*
errorInfo:
{
values: {
username: 'username',
password: 'password',
},
errorFields: [
{ name: ['password'], errors: ['Please input your Password!'] },
],
outOfDate: false,
}
*/
});
AntDesign的表單校驗(yàn)是基于async-validator,是支持異步校驗(yàn)的。
三、async-validator介紹
官方介紹:Validate form asynchronous.
簡單理解:async-validator是一個(gè)表單的異步驗(yàn)證的第三方庫。
安裝
npm i async-validator
使用
它基本用法包括定義描述符,將它分配給模式并將要驗(yàn)證的對(duì)象和回調(diào)函數(shù)傳遞給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錯(cuò)誤信息
reject('too young');
} else {
resolve();
}
});
},
},
};
const validator = new Schema(descriptor);
validator.validate({ name: 'muji' }, (errors, fields) => {
if (errors) {
// 驗(yàn)證失敗,errors 是一個(gè)包含所有錯(cuò)誤的數(shù)組
// fields 是一個(gè)以字段名稱為鍵的對(duì)象
// errors per field
return handleErrors(errors, fields);
}
// 這里則是驗(yàn)證通過
});
// PROMISE USAGE
validator.validate({ name: 'muji', age: 16 }).then(() => {
// 驗(yàn)證通過或沒有錯(cuò)誤消息
}).catch(({ errors, fields }) => {
return handleErrors(errors, fields);
});
簡單梳理下:傳入驗(yàn)證規(guī)則對(duì)象,可以新建一個(gè)驗(yàn)證器對(duì)象。驗(yàn)證器對(duì)象的validate方法用于驗(yàn)證數(shù)據(jù)是否符合驗(yàn)證規(guī)則。
Validate有三個(gè)參數(shù):
source:要驗(yàn)證的對(duì)象(必需)。
options:描述驗(yàn)證處理選項(xiàng)的對(duì)象(可選)。
callback:驗(yàn)證完成時(shí)調(diào)用的回調(diào)函數(shù)(可選)。
可以看出Validate返回了一個(gè)Promise 對(duì)象
rules規(guī)則
function(rule, value, callback, source, options)
rule:源描述符中的驗(yàn)證規(guī)則,對(duì)應(yīng)于正在驗(yàn)證的字段名稱。它總是被分配一個(gè)field帶有被驗(yàn)證字段名稱的屬性。
value:正在驗(yàn)證的源對(duì)象屬性的值。
callback:驗(yàn)證完成后調(diào)用的回調(diào)函數(shù)。它期望傳遞一個(gè)Error實(shí)例數(shù)組來指示驗(yàn)證失敗。如果檢查是同步的,可以直接返回一個(gè)falseorError或Error Array。
source:傳遞給validate方法的源對(duì)象。
options:其他選項(xiàng)。
options.messages:包含驗(yàn)證錯(cuò)誤消息的對(duì)象,將與 defaultMessages 深度合并。
傳遞給validate或asyncValidate傳遞給驗(yàn)證函數(shù)的選項(xiàng),以便在驗(yàn)證函數(shù)中引用瞬態(tài)數(shù)據(jù)(例如模型引用)。但是,保留了一些選項(xiàng)名稱;如果使用選項(xiàng)對(duì)象的這些屬性,它們將被覆蓋。保留的屬性messages是exception和error。
我們經(jīng)常寫rules為對(duì)象數(shù)組,針對(duì)單個(gè)字段的多個(gè)驗(yàn)證規(guī)則進(jìn)很有用:
const descriptor = {
email: [
{ type: 'string', required: true, pattern: Schema.pattern.email },
{
validator(rule, value, callback, source, options) {
const errors = [];
// 測(cè)試郵箱地址是否已經(jīng)存在于數(shù)據(jù)庫中
// 如果確實(shí)則將驗(yàn)證錯(cuò)誤添加到錯(cuò)誤數(shù)組
return errors;
},
},
],
};
type類型
可以使用的類型如下:
string: 必須是類型string。This is the default type.
number: 必須是類型number。
boolean: 必須是類型boolean。
method: 必須是類型function。
regexp: 必須是RegExp創(chuàng)建新的時(shí)不產(chǎn)生異常的實(shí)例或字符串RegExp。
integer: 必須是類型number和整數(shù)。
float: 必須是類型number和浮點(diǎn)數(shù)。
array: 必須是由 確定的數(shù)組Array.isArray。
object: 必須是 typeobject而不是Array.isArray。
enum: 值必須存在于enum.
date:值必須是有效的,由Date
url: 必須是類型url。
hex: 必須是類型hex。
email: 必須是類型email。
any: 可以是任何類型。
asyncValidator異步驗(yàn)證器
我們可以自定義指定字段的異步驗(yàn)證功能,代碼如下:
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)證功能,代碼如下:
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é)
在我們閱讀完官方文檔后,我們一定會(huì)進(jìn)行更深層次的學(xué)習(xí),比如看下框架底層是如何運(yùn)行的,以及源碼的閱讀。
這里廣東靚仔給下一些小建議:
在看源碼前,我們先去官方文檔復(fù)習(xí)下框架設(shè)計(jì)理念、源碼分層設(shè)計(jì)
閱讀下框架官方開發(fā)人員寫的相關(guān)文章
借助框架的調(diào)用棧來進(jìn)行源碼的閱讀,通過這個(gè)執(zhí)行流程,我們就完整的對(duì)源碼進(jìn)行了一個(gè)初步的了解
接下來再對(duì)源碼執(zhí)行過程中涉及的所有函數(shù)邏輯梳理一遍
作者:廣東靚仔
歡迎關(guān)注:前端早茶