async-validator 源码学习笔记(三):rule

时间:2024-12-10 15:14:30

系列文章:

1、async-validator 源码学习(一):文档翻译

2、async-validator 源码学习笔记(二):目录结构

rule 主要实现的是校验规则,文件结构为下图:

一、rule 目录文件介绍

其中 文件:

  1. declare const _default: {
  2. required: import("..").ExecuteRule;
  3. whitespace: import("..").ExecuteRule;
  4. type: import("..").ExecuteRule;
  5. range: import("..").ExecuteRule;
  6. enum: import("..").ExecuteRule;
  7. pattern: import("..").ExecuteRule;
  8. };
  9. export default _default;

是 rule 目录的统一出口管理,主要是给 errors 数组添加对应的 error 。

文件:

  1. import { ExecuteRule } from '../interface';
  2. declare const required: ExecuteRule;
  3. export default required;

主要作用是校验必填字段的规则。

其中 ExecuteRule 是来自于 文件中的

  1. // 摘自其中的一部分
  2. export declare type ExecuteRule = (
  3. rule: InternalRuleItem,
  4. value: Value,
  5. source: Values,
  6. errors: string[],
  7. options: ValidateOption,
  8. type?: string
  9. ) => void;
  10. /**
  11. * Performs validation for any type.
  12. *
  13. * @param rule The validation rule.
  14. * @param value The value of the field on the source object.
  15. * @param callback The callback function.
  16. * @param source The source object being validated.
  17. * @param options The validation options.
  18. * @param The validation messages.
  19. */

ExecuteRule 是统一定义的函数类型别名,统一了函数传递参数和返回值的类型。等价于:

declare const required(rule, value, source, errors, options, type) 

方法内的参数及其意义如下:

  • @param rule 校验的规则
  • @param value 需要校验字段的当前值
  • @param source 需要校验的字段
  • @param errors 本次校验将要去添加的 errors 数组
  • @param options 校验选项
  • @param 校验的 messages

  1. import { ExecuteRule } from '../interface';
  2. declare const type: ExecuteRule;
  3. export default type;

校验值的类型,可能的类型有:integer、float、array、regexp、object、method、email、number、data、url、hex

  1. import { ExecuteRule } from '../interface';
  2. declare const range: ExecuteRule;
  3. export default range;

校验是否满足最大最小值合理区间的规则

  1. import { ExecuteRule } from '../interface';
  2. /**
  3. * Rule for validating whitespace.
  4. *
  5. * @param rule The validation rule.
  6. * @param value The value of the field on the source object.
  7. * @param source The source object being validated.
  8. * @param errors An array of errors that this rule may add
  9. * validation errors to.
  10. * @param options The validation options.
  11. * @param The validation messages.
  12. */
  13. declare const whitespace: ExecuteRule;
  14. export default whitespace;

校验空白字符的规则

  1. import { ExecuteRule } from '../interface';
  2. declare const enumerable: ExecuteRule;
  3. export default enumerable;

校验值是否存在枚举值列表中的规则

  1. import { ExecuteRule } from '../interface';
  2. declare const pattern: ExecuteRule;
  3. export default pattern;

校验正则表达式的规则

二、rule 应用

中定义 rule 单元格式

  1. export interface RuleItem {
  2. type?: RuleType; //类型
  3. required?: boolean; //是否为空
  4. pattern?: RegExp | string; //正则
  5. min?: number; // 最小值或长度
  6. max?: number; //最大值或长度
  7. len?: number; // 长度
  8. enum?: Array<string | number | boolean | null | undefined>; //校验值是否存在枚举值列表中的规则
  9. whitespace?: boolean; //是否空白
  10. fields?: Record<string, Rule>;//深度监听属性和规则
  11. options?: ValidateOption;//选项
  12. defaultField?: Rule; //校验属性内部值
  13. transform?: (value: Value) => Value; //校验前转换
  14. message?: string | ((a?: string) => string);//信息提示
  15. //异步校验
  16. asyncValidator?: (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void, source: Values, options: ValidateOption) => void | Promise<void>;
  17. //同步校验
  18. validator?: (rule: InternalRuleItem, value: Value, callback: (error?: string | Error) => void, source: Values, options: ValidateOption) => SyncValidateResult | void;
  19. }
  20. // Rule 可以是一个对象,也可以是该对象的数组
  21. export declare type Rule = RuleItem | RuleItem[];

rule 是本字段对应的校验规则:

  1. {
  2. field: "name",
  3. fullField: "name",
  4. message: "姓名为必填项",
  5. required: false,
  6. type: "string",
  7. validator: ƒ required$1(rule, value, callback, source, options)
  8. }

value 是本字段的值:如小明

source 是要校验的整个 source 对象:

  1. {
  2. name: '小明',
  3. info: {
  4. age: 17,
  5. }
  6. }

errors 是本次校验将要去添加的 errors 数组,假设之前没有 error,则 errors 为[],如果之前已经存在了一些 error,则格式如下所示:

  1. [
  2. {
  3. message: '年龄超出范围',
  4. field: ''
  5. }
  6. ]

options 是该字段校验时的选项,当 message 属性为默认值时,格式如下:

  1. {
  2. firstFields: true,
  3. messages: {
  4. array: {len: "%s must be exactly %s in length", min: "%s cannot be less than %s in length", max: "%s cannot be greater than %s in length", range: "%s must be between %s and %s in length"},
  5. clone: ƒ clone(),
  6. date: {format: "%s date %s is invalid for format %s", parse: "%s date could not be parsed, %s is invalid ", invalid: "%s date %s is invalid"},
  7. default: "Validation error on field %s",
  8. enum: "%s must be one of %s",
  9. number: {len: "%s must equal %s", min: "%s cannot be less than %s", max: "%s cannot be greater than %s", range: "%s must be between %s and %s"},
  10. pattern: {mismatch: "%s value %s does not match pattern %s"},
  11. required: "%s is required",
  12. string: {len: "%s must be exactly %s characters", min: "%s must be at least %s characters", max: "%s cannot be longer than %s characters", range: "%s must be between %s and %s characters"},
  13. types: {string: "%s is not a %s", method: "%s is not a %s (function)", array: "%s is not an %s", object: "%s is not an %s", number: "%s is not a %s", …},
  14. whitespace: "%s cannot be empty",
  15. }
  16. }

三、项目开发应用

实际项目开发中验证规则 rule 的写法:

  1. const rules = {
  2. // 深度校验1
  3. address: {
  4. type: 'object',
  5. required: true,
  6. fields: {
  7. //深度校验street属性
  8. street: { type: 'string', required: true },
  9. city: { type: 'string', required: true },
  10. zip: {
  11. type: 'string',
  12. required: true,
  13. len: 8,
  14. message: 'invalid zip',
  15. },
  16. },
  17. },
  18. //校验 2 数组形式
  19. username: [
  20. {
  21. type: 'string',
  22. required: true,
  23. whitespace: true,
  24. transform(value) {
  25. return value.trim()
  26. },
  27. message: '用户名不能为空格',
  28. // 异步校验
  29. asyncValidator: (rule, value) => {
  30. return new Promise((resolve, reject) => {
  31. setTimeout(() => {
  32. if (value != '') {
  33. resolve()
  34. } else {
  35. reject('error')
  36. }
  37. }, 2000)
  38. })
  39. },
  40. },
  41. {
  42. type: 'string',
  43. min: 3,
  44. max: 20,
  45. message: '长度 3- 20 位',
  46. },
  47. ],
  48. }