async-validator:基于 JavaScript 的异步表单验证工具

validate form asynchronous

分支3Tags80
文件最后提交记录最后更新时间
4 年前
4 年前
4 年前
4 年前
4 年前
11 年前
4 年前
4 年前
6 年前
4 年前
4 年前
4 年前
9 年前
4 年前
4 年前
4 年前
4 年前

异步验证器

NPM版本 构建状态 覆盖率 Node.js 版本 下载量 gzip 包大小

异步表单验证。基于 https://github.com/freeformsystems/async-validate 的一个变体。

安装

npm i async-validator

使用

基本使用包括定义描述符,将其分配给模式,并将要验证的对象和回调函数传递给模式的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('too young');  // 拒绝并返回错误信息
        } else {
          resolve();
        }
      });
    },
  },
};
const validator = new Schema(descriptor);
validator.validate({ name: 'muji' }, (errors, fields) => {
  if (errors) {
    // 验证失败,errors 是所有错误的数组
    // fields 是按字段名键值对存储的错误对象
    return handleErrors(errors, fields);
  }
  // 验证通过
});

// 用法 - 承诺
validator.validate({ name: 'muji', age: 16 }).then(() => {
  // 验证通过或者没有错误消息
}).catch(({ errors, fields }) => {
  return handleErrors(errors, fields);
});

API

验证

function(source, [options], callback): Promise
  • source: 要验证的对象(必需)。
  • options: 描述验证处理选项的对象(可选)。
  • callback: 验证完成时调用的回调函数(可选)。

该方法会返回一个Promise对象:

  • then(),验证成功
  • catch({ errors, fields }),验证失败,errors是所有错误的数组,fields是按字段名键值对存储的每个字段的错误数组

选项

  • suppressWarning: 布尔值,是否抑制内部关于无效值的警告。

  • first: 布尔值,当第一个验证规则产生错误时调用callback,不再处理其他规则。如果您的验证涉及多个异步调用(例如数据库查询),并且只需要第一个错误,则可以使用此选项。

  • firstFields: 布尔值 | 字符串数组,当指定字段的第一个验证规则产生错误时调用callback,不再处理同一字段的其他规则。true表示所有字段。

规则

规则可以是执行验证的函数。

function(rule, value, callback, source, options)
  • rule: 在源描述符中对应于正在验证的字段名称的验证规则。它总是有一个名为field的属性,包含正在验证的字段的名称。
  • value: 正在验证的源对象属性的值。
  • callback: 验证完成后调用的函数。期望接收一个表示验证失败的Error实例数组。如果检查是同步的,您可以直接返回falseErrorError数组。
  • source: 传递给validate方法的源对象。
  • options: 其他选项。
  • options.messages: 含有验证错误消息的对象,将与defaultMessages深度合并。

传递给validateasyncValidate的选项将传递给验证函数,以便您可以在验证函数中引用临时数据(如模型引用)。但是,某些选项名称是保留的;如果你使用这些选项对象的属性,它们会被覆盖。保留的属性有messagesexceptionerror

import Schema from 'async-validator';
const descriptor = {
  name(rule, value, callback, source, options) {
    const errors = [];
    if (!/^[a-z0-9]+$/.test(value)) {
      errors.push(new Error(
        util.format('%s 必须是小写字母数字字符', rule.field),
      ));
    }
    return errors;
  },
};
const validator = new Schema(descriptor);
validator.validate({ name: 'Firstname' }, (errors, fields) => {
  if (errors) {
    return handleErrors(errors, fields);
  }
  // 验证通过
});

经常需要针对单个字段测试多个验证规则,为此,使规则成为一个包含对象的数组,例如:

const descriptor = {
  email: [
    { type: 'string', required: true, pattern: Schema.pattern.email },
    { 
      validator(rule, value, callback, source, options) {
        const errors = [];
        // 测试电子邮件地址是否已存在于数据库中
        // 如果存在,则向错误数组添加一个验证错误
        return errors;
      },
    },
  ],
};

类型

指示要使用的验证器类型。认可的类型值有:

  • string: 必须是字符串类型。这是默认类型。
  • number: 必须是数字类型。
  • boolean: 必须是布尔类型。
  • method: 必须是函数类型。
  • regexp: 必须是RegExp实例或创建新RegExp时不会抛出异常的字符串。
  • integer: 必须是数字类型且为整数。
  • float: 必须是数字类型且为浮点数。
  • array: 必须通过Array.isArray确定为数组。
  • object: 必须是类型为object而不是Array.isArray的对象。
  • enum: 值必须存在于枚举中。
  • date: 值必须是有效的日期。
  • url: 必须是URL类型。
  • hex: 必须是十六进制类型。
  • email: 必须是电子邮件类型。
  • any: 可以是任何类型。

必需

required规则属性表明验证的源对象上必须存在该字段。

模式

pattern规则属性指示值必须匹配的正则表达式才能通过验证。

范围

范围使用minmax属性定义。对于stringarray类型,比较是在length上进行的,对于number类型,数字不能小于min或大于max

长度

要验证字段的确切长度,指定len属性。对于stringarray类型,比较的是length属性,对于number类型,该属性表示与len严格相等。

如果len属性与minmax范围属性结合使用,len优先。

枚举

自从版本3.0.0,如果您想在enum类型中验证值0false,您必须明确地包含它们。

要从可能的值列表中验证值,使用enum类型并将有效的字段值列表赋给enum属性,例如:

const descriptor = {
  role: { type: 'enum', enum: ['admin', 'user', 'guest'] },
};

空白

通常认为只含有空白的必要字段是错误的。要在规则中添加一个额外的测试以检测仅由空格组成的字符串,将whitespace属性设置为true。该规则必须是string类型。

您可能希望清理用户输入,而不是测试空白,参阅transform示例,该示例允许您删除空白。

深度规则

如果需要验证深层对象属性,可以通过将嵌套规则分配给规则的fields属性来为objectarray类型的规则执行此操作。

const descriptor = {
  address: {
    type: 'object',
    required: true,
    fields: {
      street: { type: 'string', required: true },
      city: { type: 'string', required: true },
      zip: { type: 'string', required: true, len: 8, message: 'invalid zip' },
    },
  },
  name: { type: 'string', required: true },
};
const validator = new Schema(descriptor);
validator.validate({ address: {} }, (errors, fields) => {
  // 地址.street、地址.city、地址.zip 的错误
});

请注意,如果不为父规则指定required属性,那么即使字段没有在源对象上声明,也是完全合法的,因为没有什么要验证的,所以深层验证规则不会执行。

深度规则验证会为嵌套规则创建一个架构,因此您也可以指定传递给schema.validate()方法的options

const schemaDescriptor = {
  address: {
    type: 'object',
    presence: true,
    priority: true,
    fields: {
      street: { type: 'string', presence: true },
      city: { type: 'string', presence: true },
      zip: {
        type: 'string',
        presence: true,
        length: { exactly: 8 },
        errorMessage: 'invalid zip code',
      },
    },
  },
  name: { type: 'string', presence: true },
};

const schemaValidator = new Schema(schemaDescriptor);

schemaValidator.validate({ address: {} })
  .catch(({ errors, invalidFields }) => {
    // At this point, errors only concern the 'street' and 'name'
  });

当规则如以下所示时,父级规则也会被验证:

const roleDescriptor = {
  roles: {
    type: 'array',
    presence: true,
    length: { exactly: 3 },
    fields: {
      0: { type: 'string', presence: true },
      1: { type: 'string', presence: true },
      2: { type: 'string', presence: true },
    },
  },
};

// 假设提供的数据是 { roles: ['admin', 'user'] }
// 那么会生成两个错误:一个是因为数组长度不符,另一个是因为索引为2的必需数组条目缺失

默认字段(defaultField)

defaultField 属性可用于 arrayobject 类型,以对容器中的所有值进行验证。它可以是一个包含验证规则的 objectarray,例如:

const descriptor = {
  urls: {
    type: 'array',
    presence: true,
    defaultField: { type: 'url' },
  },
};

请注意,defaultField 将扩展为 fields,详情见深度规则部分。

转换(Transform)

有时在验证之前需要转换值,可能是为了强制类型转换,或者以某种方式清理值。为此,在验证规则中添加一个 transform 函数。属性在验证前进行转换,并作为通过验证后的承诺结果或回调结果返回。

import Schema from 'async-validator';
const descriptor = {
  name: {
    type: 'string',
    presence: true,
    pattern: /^[a-z]+$/,
    transform(value) {
      return value.trim();
    },
  },
};

const validator = new Schema(descriptor);
const dataSource = { name: ' user  ' };

validator.validate(dataSource)
  .then((data) => assert.equal(data.name, 'user'));

validator.validate(dataSource, (errors, data) => {
  assert.equal(data.name, 'user'));
});

如果没有 transform 函数,由于输入带有前后空格,模式匹配会失败,但通过添加这个转换函数,验证成功并且字段值得到了清理。

消息(Messages)

根据应用程序需求,您可能需要国际化支持,或者希望使用不同的验证错误消息。

最简单的方法是在规则上分配一个 message

{ name: { type: 'string', presence: true, message: 'Name is required' } }

消息可以是任意类型,比如 JSX 格式:

{ name: { type: 'string', presence: true, message: '<b>Name is required</b>' } }

消息也可以是一个函数,例如,如果你使用 vue-i18n:

{ name: { type: 'string', presence: true, message: () => this.$t('name is required') } }

可能有些情况下,你需要用不同的语言对相同的 schema 规则进行验证,直接为每种语言复制 schema 规则并不合理。

在这种情况下,你可以为指定的语言提供自己的消息,并将其分配给 schema:

import Schema from 'async-validator';
const chineseMessages = {
  presence: '%s 是必填项',
};
const descriptor = { name: { type: 'string', presence: true } };
const validator = new Schema(descriptor);
// 合并到默认消息
validator.messages(chineseMessages);
...

如果你定义了自己的验证函数,最好实践是在消息对象中分配消息字符串,然后在验证函数内部通过 options.messages 属性访问这些消息。

自定义异步验证器(asyncValidator)

可以为指定字段自定义异步验证函数:

const fields = {
  asyncField: {
    asyncValidator: (rule, value, callback) => {
      ajax({
        url: 'xx',
        value: value,
      }).then(callback, (error) => callback(new Error(error)));
    },
  },

  promiseField: {
    asyncValidator: (rule, value) =>
      ajax({
        url: 'xx',
        value: value,
      }),
  },
};

自定义验证器(validator)

可以为特定字段定制验证函数:

const fields = {
  field: {
    validator: (rule, value, callback) => callback(value === 'test'),
    errorMessage: 'Value does not equal "test".',
  },

  field2: {
    validator: (rule, value, callback) => callback(new Error(`${value} is not equal to 'test'.`)),
  },

  arrField: {
    validator: (rule, value) => [
      new Error('Message 1'),
      new Error('Message 2'),
    ],
  },
};

经常问的问题(FAQ)

如何避免全局警告

import Schema from 'async-validator';
Schema.warning = () => {};

或者

globalThis.ASYNC_VALIDATOR_NO_WARNING = 1;

如何检查是否为 true

使用 enum 类型,将选项设置为 true

{
  type: 'enum',
  enum: [true],
  errorMessage: '',
}

测试案例

npm test

代码覆盖率

npm run coverage

打开 coverage/ 目录

许可证

一切都是 MIT 许可证。

项目介绍

验证表单异步处理【此简介由AI生成】

定制我的领域
1099.1 K765访问 GitHub