async-validator 源码解析(四):Schema 类
2024-02-07 20:40:33
在上一篇文章中,我们分析了 async-validator 校验库的 validator 目录下的代码。这次,我们将继续自底向上进入到最上层 index.js,分析 async-validator 校验库的核心 Schema 类。
Schema 类
Schema 类是 async-validator 校验库的核心类,负责解析规则、验证数据、收集错误信息等核心功能。Schema 类的构造函数如下:
export default class Schema {
constructor() {
this.rules = null;
this.messages = {};
this._messages = [];
this._errorClass = Error;
this.silent = false;
}
}
从构造函数可以看出,Schema 类具有以下属性和方法:
rules
:存储校验规则的对象。messages
:存储校验错误信息的国际化文案。_messages
:存储校验错误信息。_errorClass
:自定义的错误类,默认为Error
。silent
:是否静默模式,默认为false
。
解析规则
Schema 类提供了 add
方法来解析校验规则:
add(field, rule) {
if (Array.isArray(field)) {
field.forEach(field => {
this.add(field, rule);
});
return this;
}
const { message, ...ruleWithoutMessage } = normalizeRule(rule);
if (message) {
this._messages.push({
field,
message
});
}
this.rules = this.rules || {};
this.rules[field] = ruleWithoutMessage;
return this;
}
add
方法可以接受两个参数:field
和 rule
。field
是要校验的字段,可以是字符串或数组,rule
是校验规则,可以是对象或函数。
如果 field
是数组,add
方法会对数组中的每个字段分别添加校验规则。
如果 rule
是对象,add
方法会将 rule
中的 message
属性单独提取出来,并将其存储在 _messages
数组中。然后,add
方法会将 rule
中除了 message
属性以外的其他属性存储在 rules
对象中。
如果 rule
是函数,add
方法会直接将 rule
存储在 rules
对象中。
验证数据
Schema 类提供了 validate
方法来验证数据:
async validate(data, options = {}) {
const opts = Object.assign({}, this.options, options);
await Promise.all(
Object.keys(this.rules).map(async field => {
const fieldValidationPromises = this._validateField(field, data[field], opts);
const fieldErrors = await Promise.all(fieldValidationPromises);
// Concatenate all errors of this field to `_errors`
this._errors = this._errors.concat(
this._processErrors(fieldErrors, field, opts)
);
})
);
return this._errors;
}
validate
方法可以接受两个参数:data
和 options
。data
是要验证的数据,options
是可选的配置项。
validate
方法首先会将 options
与 this.options
合并,然后对 this.rules
对象中的每个字段进行校验。
对于每个字段,validate
方法会调用 _validateField
方法来验证字段的值。_validateField
方法会返回一个 Promise,该 Promise 会在校验完成后被解析。
validate
方法会等待所有字段的校验完成,然后将所有字段的校验错误信息收集到 _errors
数组中。最后,validate
方法会返回 _errors
数组。
收集错误信息
Schema 类提供了 _processErrors
方法来收集错误信息:
_processErrors(errors, field, options = {}) {
if (!errors.length) {
return [];
}
const processedErrors = errors
.map(({ message, rule, type }) => {
if (typeof message === 'function') {
message = message(
options.messages || this.messages,
field,
type
);
} else if (typeof message === 'string') {
message = i18n(
options.messages || this.messages,
message,
field,
type
);
}
return {
message,
field,
rule,
type
};
})
.filter(
({ message, field }) => !this.silent && this._checkFieldInSchema(field)
);
if (this.silent) {
return [];
}
if (this._hasRulesInSchema(field)) {
return processedErrors;
}
return [];
}
_processErrors
方法可以接受三个参数:errors
、field
和 options
。errors
是要处理的错误信息数组,field
是校验字段,options
是可选的配置项。
_processErrors
方法首先会检查 errors
数组是否为空。如果为空,则直接返回空数组。
如果 errors
数组不为空,_processErrors
方法会对数组中的每个错误信息进行处理。
对于每个错误信息,_processErrors
方法会先检查 message
属性是否为函数。如果是函数,则会调用 message
函数来获取错误信息。否则,_processErrors
方法会直接使用 message
属性作为错误信息。
然后,_processErrors
方法会检查 this.silent
属性是否为 true
。如果是,则会过滤掉所有错误信息。
最后,_processErrors
方法会检查 field
字段在 this.rules
对象中是否存在。如果存在,则会将处理后的错误信息返回。否则,会返回空数组。
总结
Schema 类是 async-validator 校验库的核心类,负责解析规则、验证数据、收集错误信息等核心功能。通过分析 Schema 类的源码,我们可以更好地理解 async-validator 校验库的工作原理。