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

396 阅读4分钟

系列文章:

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

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

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

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

一、rule 目录文件介绍

其中 index.d.ts 文件:

declare const _default: {
 required: import("..").ExecuteRule;
 whitespace: import("..").ExecuteRule;
 type: import("..").ExecuteRule;
 range: import("..").ExecuteRule;
 enum: import("..").ExecuteRule;
 pattern: import("..").ExecuteRule;
};
export default _default;

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

required.d.ts 文件:

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

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

其中 ExecuteRule 是来自于 interface.d.ts 文件中的

// 摘自其中的一部分
export declare type ExecuteRule = (
 rule: InternalRuleItem, 
 value: Value, 
 source: Values, 
 errors: string[], 
 options: ValidateOption, 
 type?: string
) => void;
/**
 *  Performs validation for any type.
 *
 *  @param rule The validation rule.
 *  @param value The value of the field on the source object.
 *  @param callback The callback function.
 *  @param source The source object being validated.
 *  @param options The validation options.
 *  @param options.messages The validation messages.
 */

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

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

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

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

type.d.ts

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

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

range.d.ts

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

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

whitespace.d.ts

import { ExecuteRule } from '../interface';
/**
 *  Rule for validating whitespace.
 *
 *  @param rule The validation rule.
 *  @param value The value of the field on the source object.
 *  @param source The source object being validated.
 *  @param errors An array of errors that this rule may add
 *  validation errors to.
 *  @param options The validation options.
 *  @param options.messages The validation messages.
 */
declare const whitespace: ExecuteRule;
export default whitespace;

校验空白字符的规则

enum.d.ts

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

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

pattern.d.ts

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

校验正则表达式的规则

二、rule 应用

interface.d.ts 中定义 rule 单元格式

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

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

{
 field: "name",
 fullField: "name",
 message: "姓名为必填项",
 required: false,
 type: "string",
 validator: ƒ required$1(rule, value, callback, source, options)
}

value 是本字段的值:如小明

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

{
 name: '小明',
 info: {
  age: 17,
 }
}

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

[ {  message: '年龄超出范围',  field: 'info.age', }]

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

{
 firstFields: true,
 messages: {
  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"},
  clone: ƒ clone(),
  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"},
  default: "Validation error on field %s",
  enum: "%s must be one of %s",
  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"},
  pattern: {mismatch: "%s value %s does not match pattern %s"},
  required: "%s is required",
  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"},
  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", …},
  whitespace: "%s cannot be empty",
 }
}

三、项目开发应用

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

const rules = {
 // 深度校验1
 address: {
  type: 'object',
  required: true,
  fields: {
   //深度校验street属性
   street: { type: 'string', required: true },
   city: { type: 'string', required: true },
   zip: {
    type: 'string',
    required: true,
    len: 8,
    message: 'invalid zip',
   },
  },
 },
 //校验 2 数组形式
 username: [
  {
   type: 'string',
   required: true,
   whitespace: true,
   transform(value) {
    return value.trim()
   },
   message: '用户名不能为空格',
   // 异步校验
   asyncValidator: (rule, value) => {
    return new Promise((resolve, reject) => {
     setTimeout(() => {
      if (value != '') {
        resolve()
       } else {
         reject('error')
       }
      }, 2000)
     })
    },
   },
   {
    type: 'string',
    min: 3,
    max: 20,
    message: '长度 3- 20 位',
   },
  ],
}