返回
async-validator源码解析(二):rule
前端
2023-09-17 18:21:41
在上篇 async-validator 源码解析(一):文档翻译 中,我们已经将 ElementUI 和 Ant Design 都依赖的 async-validator 校验库的文档进行了翻译,下面继续来填坑分析 async-validator 的源码,理解表单校验的原理。可以从仓库 https://github.com/yiminghe/async-validator 获取源码。
源码位置
packages/async-validator/src/rule.js
相关类
Field 校验的字段
Rule 具体的校验规则
FieldEntity 一个字段的所有规则组成的对象
字段
/**
* 校验字段的具体校验规则
*
* @example
* ```
* const rule = {
* required: true,
* min: 10,
* max: 20,
* pattern: /^[a-zA-Z0-9]+$/
* };
* ```
*/
export class Rule {
/**
* 校验函数的返回结果
*
* @typedef {Object} RuleResult
* @property {*} value 校验字段的实际值
* @property {string} rule 校验字段的规则,key就是校验规则的名称,value是对应的校验规则的配置
* @property {boolean} valid 是否符合校验规则,如果校验通过返回 `true`,否则返回 `false`
* @property {string} message 错误提示信息,校验不通过的时候返回错误信息
*/
/**
* @param {string} name 校验规则的名称
* @param {RuleOptions} [options] 校验规则的配置
*/
constructor(name, options = {}) {
this.name = name;
this.message = options.message || FieldEntity.get(name, 'messages', '');
this.trigger = options.trigger === null ? [] : options.trigger;
this.triggerType = options.triggerType;
this.exclusive = !!options.exclusive;
this.validator = options.validator;
this.validate = options.validate;
this.async = !!options.async;
this.params = options.params;
}
/**
* 校验字段的值
*
* @param {*} value 校验字段的实际值
* @param {string} [rule] 校验字段的规则,key就是校验规则的名称,value是对应的校验规则的配置
* @param {FieldEntity} field 校验的字段
* @param {string} [source] 字段校验时产生校验结果的源字段名
* @param {boolean} [silent] 是否在校验不通过的情况下不抛出错误
* @returns {RuleResult} 校验结果
*/
validate(value, rule, field, source, silent) {
let errors;
let result;
const { message, validator, validate, triggerType } = this;
if (typeof rule === 'string') {
result = {
rule: rule,
value,
valid: true
};
} else {
result = rule;
result.value = value;
if (field && triggerType === 'change' && !field.required) {
result.valid = true;
}
}
if (triggerType === 'change' && field && field.required && result.valid && value === field.initialValue) {
return result;
}
if (this.async) {
errors = validator
? Promise.resolve(this.validator(value, rule, field, source))
: validate(value, rule, field, source, this.params);
errors = errors.catch((err) => {
if (err instanceof Error) {
err.message = message;
}
return err;
});
return errors.then((errors) => {
if (Array.isArray(errors)) {
errors.forEach((err) => {
err.field = source;
err.message = message;
});
result.valid = false;
return errors;
} else {
result.valid = !errors;
return result;
}
}, (err) => {
if (err instanceof Error) {
err.message = message;
}
result.valid = false;
return err;
});
}
if (validator) {
errors = this.validator(value, rule, field, source);
} else if (validate) {
errors = validate(value, rule, field, source, this.params);
}
if (errors === true) {
return result;
}
if (Array.isArray(errors)) {
errors.forEach((err) => {
err.field = source;
err.message = message;
});
result.valid = false;
return errors;
} else if (errors instanceof Error) {
errors.message = message;
result.valid = false;
return errors;
} else if (typeof errors === 'string') {
result.valid = false;
return errors;
}
return result;
}
}
方法
/**
* 校验给定字段
*
* @param {*} value 校验字段的实际值
* @param {string} rule 校验字段的规则,key就是校验规则的名称,value是对应的校验规则的配置
* @param {FieldEntity} field 校验的字段
* @param {string} [source] 字段校验时产生校验结果的源字段名
* @param {boolean} [silent] 是否在校验不通过的情况下不抛出错误
* @returns {Promise<RuleResult | RuleResult[]>} 校验结果
*/
static validate(value, rule, field, source, silent) {
if (Array.isArray(rule)) {
return Promise.all(rule.map((subRule) => {
const result = Rule.validate(value, subRule, field, source, silent);
if (result instanceof Error) {
throw result;
}
if (result.valid === false) {
throw new Error(result.message);
}
return result;
}));
}
if (rule instanceof Rule) {
return rule.validate(value, rule, field, source, silent);
}
if (typeof rule === 'string') {
rule = FieldEntity.get(rule);
}
return new Rule(rule).validate(value, rule, field, source, silent);
}
总结
async-validator 的 Rule 类是具体校验规则的封装,包含了校验函数、错误提示信息、触发时机等信息。validate 方法可以对给定字段进行校验,并返回校验结果。Rule 类是 async-validator 校验库的核心组成部分,也是理解表单校验原理的基础。