async-validator 的中文文檔翻譯

阿里出品的 antdElementUI 組件庫中表單校驗默認使用的 async-validator,它在 gitbub 上也得到了 3.8k 的 star,可見這個庫十分強大,奈何只有英文文檔看的蛋疼,所以花點時間翻譯一下以便往後查看和爲新手同事提供文檔,原文都以摺疊的方式保留着,看不懂個人描述能夠展開看看原文。javascript

結合 github 上的例子能方便理解vue

(大部分緣由是我英文水平不夠,可是明明是中國人寫的爲啥不順手寫個中文的 readme 呢,雖然就算翻譯成了中文也仍是晦澀難懂。。。)java

翻譯時間: 2019/5/31ios

正文開始。git


async-validator

一個用於表單異步校驗的庫,參考了 https://github.com/freeformsystems/async-validate
github


Validate form asynchronous. A variation of https://github.com/freeformsystems/async-validate

API

下述內容來自於 async-validate. 的早期版本
ajax


The following is modified from earlier version of async-validate.

Usage 使用方法

基本的使用方法:定義一個 descriptor,將它傳入 schema,獲得一個 validator。將須要校驗的對象和回調傳入 validator.validate 方法中。數據庫

注:descriptor 是對校驗規則的描述,validator 是根據校驗規則獲得的校驗器express

Basic usage involves defining a descriptor, assigning it to a schema and passing the object to be validated and a callback function to the `validate` method of the schema:
var schema = require('async-validator');
var descriptor = {
  name: {
    type: "string",
    required: true,
    validator: (rule, value) => value === 'muji',
  },
};
var validator = new schema(descriptor);
validator.validate({name: "muji"}, (errors, fields) => {
  if(errors) {
    // validation failed, errors is an array of all errors
    // fields is an object keyed by field name with an array of
    // errors per field

    // 校驗未經過的狀況,errors 是全部錯誤的數組
    // fields 是一個 object,以字段做爲 key 值,該字段對應的錯誤數組做爲 value
    // (其實 fields 就是把 errors 按照原對象的 key 值分組)

    return handleErrors(errors, fields);
  }

  // validation passed
  // 這裏說明校驗已經過
});

// PROMISE USAGE
// Promise 式用法

validator.validate({
  name: "muji",
  asyncValidator: (rule, value) => axios.post('/nameValidator', { name: value }),
}, (errors, fields) => {
  if(errors) {
    // validation failed, errors is an array of all errors
    // fields is an object keyed by field name with an array of
    // errors per field

    // 校驗未經過的狀況,errors 和 fields 同上
    return handleErrors(errors, fields);
  }
  // validation passed
  // 校驗經過
})
  .then(() => {
    // validation passed
    // 校驗經過
  })
  .catch(({ errors, fields }) => {
    return handleErrors(errors, fields);
  })

Validate 方法參數

function(source, [options], callback): Promise
  • source: 須要校驗的對象(必填).
  • options: 校驗選項(可選).
  • callback: 校驗完成時的回調(必填).
* `source`: The object to validate (required). * `options`: An object describing processing options for the validation (optional). * `callback`: A callback function to invoke when validation completes (required).

方法返回一個 Promise 對象:axios

  • then(),說明校驗經過
  • catch({ errors, fields }),校驗未經過,errors, fields 含義見前面示例
The method will return a Promise object like: * `then()`,validation passed * `catch({ errors, fields })`,validation failed, errors is an array of all errors, fields is an object keyed by field name with an array of

Options 選項

  • first: Boolean, 碰見第一個未經過校驗的值時便調用 callback 回調,再也不繼續校驗剩餘規則。
    適用狀況:校驗涉及到多個異步調用,好比數據庫查詢,而你只須要獲取首個校驗錯誤時

  • firstFields: Boolean|String[], 對於指定字段,碰見第一條未經過的校驗規則時便調用 callback 回調,而再也不校驗該字段的其餘規則 ,傳入 true 表明全部字段。

* `first`: Boolean, Invoke `callback` when the first validation rule generates an error, no more validation rules are processed. If your validation involves multiple asynchronous calls (for example, database queries) and you only need the first error use this option. * `firstFields`: Boolean|String[], Invoke `callback` when the first validation rule of the specified field generates an error, no more validation rules of the same field are processed. `true` means all fields.

Rules

Rules 也能夠是用於校驗的函數

Rules may be functions that perform validation.
function(rule, value, callback, source, options)
  • rule: 當前校驗字段在 descriptor 中所對應的校驗規則,其中的 field 屬性是當前正在校驗字段的名稱
  • value: 當前校驗字段的值
  • callback: 在校驗完成時的回調,傳入 Error [或者是一個數組] 表明校驗失敗,若是校驗是同步的話,直接返回 falseErrorError 數組也能夠(注:異步校驗經過時直接不帶參數調用 callback(),表明沒有錯誤)
  • source: 傳入 validate 方法的 object,也就是須要校驗的對象
  • options: 傳入的額外選項
  • options.messages: 對象包含的校驗錯誤提示信息,會被合併到默認的提示信息中
* `rule`: The validation rule in the source descriptor that corresponds to the field name being validated. It is always assigned a `field` property with the name of the field being validated. * `value`: The value of the source object property being validated. * `callback`: A callback function to invoke once validation is complete. It expects to be passed an array of `Error` instances to indicate validation failure. If the check is synchronous, you can directly return a ` false ` or ` Error ` or ` Error Array `. * `source`: The source object that was passed to the `validate` method. * `options`: Additional options. * `options.messages`: The object containing validation error messages, will be deep merged with defaultMessages.

傳入 validateasyncValidate 的 options 被帶到了校驗函數中,以便你能夠在校驗函數中拿到數據(好比 model 引用)。然而,option中部分屬性名是被保留的,你若是使用了的話會被覆蓋掉,其中包括 messages, exceptionerror

The options passed to `validate` or `asyncValidate` are passed on to the validation functions so that you may reference transient data (such as model references) in validation functions. However, some option names are reserved; if you use these properties of the options object they are overwritten. The reserved properties are `messages`, `exception` and `error`.
var schema = require('async-validator');
var descriptor = {
  name(rule, value, callback, source, options) {
    var errors = [];
    if(!/^[a-z0-9]+$/.test(value)) {
      errors.push(
        new Error(
          util.format("%s must be lowercase alphanumeric characters",
            rule.field)));
    }
    return errors;
  }
}
var validator = new schema(descriptor);
validator.validate({name: "Firstname"}, (errors, fields) => {
  if(errors) {
    return handleErrors(errors, fields);
  }
  // validation passed
});

在須要對一個字段設置多條校驗規則時,能夠把規則設爲一個數組,好比

It is often useful to test against multiple validation rules for a single field, to do so make the rule an array of objects, for example:
var descriptor = {
  email: [
    {type: "string", required: true, pattern: schema.pattern.email},
    {validator(rule, value, callback, source, options) {
      var errors = [];
      // test if email address already exists in a database
      // and add a validation error to the errors array if it does
      return errors;
    }}
  ]
}

Type 內置類型

下列是 type 可用的值:

  • string: 必須是 string. This is the default type.
  • number: 必須是 number.
  • boolean: 必須是 boolean.
  • method: 必須是 function.
  • regexp: 必須是正則或者是在調用 new RegExp 時不報錯的字符串.
  • integer: 整數.
  • float: 浮點數.
  • array: 必須是數組,經過 Array.isArray 判斷.
  • object: 是對象且不爲數組.
  • enum: 值必須出如今 enmu 枚舉值中.
  • date: 合法的日期,使用 Date 判斷
  • url: url.
  • hex: 16進制.
  • email: 郵箱地址.
Indicates the `type` of validator to use. Recognised type values are: * `string`: Must be of type `string`. `This is the default type.` * `number`: Must be of type `number`. * `boolean`: Must be of type `boolean`. * `method`: Must be of type `function`. * `regexp`: Must be an instance of `RegExp` or a string that does not generate an exception when creating a new `RegExp`. * `integer`: Must be of type `number` and an integer. * `float`: Must be of type `number` and a floating point number. * `array`: Must be an array as determined by `Array.isArray`. * `object`: Must be of type `object` and not `Array.isArray`. * `enum`: Value must exist in the `enum`. * `date`: Value must be valid as determined by `Date` * `url`: Must be of type `url`. * `hex`: Must be of type `hex`. * `email`: Must be of type `email`.

Required

required 屬性表明這個字段必須出如今對象中

The `required` rule property indicates that the field must exist on the source object being validated.

Pattern

pattern 屬性表明須要符合的正則

The `pattern` rule property indicates a regular expression that the value must match to pass validation.

Range

使用 minmax 屬性定義範圍,對於字符串和數組會與 value.length 比較,對於數字會直接與值比較

A range is defined using the `min` and `max` properties. For `string` and `array` types compariso is performed against the `length`, for `number` types the number must not be less than `min` nor greater than `max`.

Length

使用 len 屬性直接指定長度,會與字符串和數組的 value.length 比較相等,對於數字會直接與值比較是否相等
若是 lenminmax 同時使用, len 優先。

To validate an exact length of a field specify the `len` property. For `string` and `array` types comparison is performed on the `length` property, for the `number` type this property indicates an exact match for the `number`, ie, it may only be strictly equal to `len`. If the `len` property is combined with the `min` and `max` range properties, `len` takes precedence.

Enumerable

可枚舉值

對於能夠枚舉出全部狀況的類型,可使用枚舉校驗,以下:

To validate a value from a list of possible values use the `enum` type with a `enum` property listing the valid values for the field, for example:
var descriptor = {
  role: {type: "enum", enum: ['admin', 'user', 'guest']}
}

Whitespace

把僅包含空格的字段視爲錯誤是很典型的作法,爲了額外測試字段是否只有空格,添加 whitespace 屬性並設爲true。這個屬性要求字段必須爲 string 類型。

若是你想要修正用戶的輸入而不是測試有無空格,查看 transform 中去除空格的例子。

It is typical to treat required fields that only contain whitespace as errors. To add an additional test for a string that consists solely of whitespace add a `whitespace` property to a rule with a value of `true`. The rule must be a `string` type. You may wish to sanitize user input instead of testing for whitespace, see [transform](#transform) for an example that would allow you to strip whitespace.

Deep Rules 深層規則

若是須要校驗一個深層的對象,你須要使用 fields 屬性來設置嵌套的規則

If you need to validate deep object properties you may do so for validation rules that are of the `object` or `array` type by assigning nested rules to a `fields` property of the rule.
var 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}
}
var validator = new schema(descriptor);
validator.validate({ address: {} }, (errors, fields) => {
  // errors for address.street, address.city, address.zip
});

須要注意的是,若是沒有在父規則上指定 required 屬性,在校驗對象中不存在這個屬性是徹底合法的,嵌套的深層規則也不會運行。

Note that if you do not specify the `required` property on the parent rule it is perfectly valid for the field not to be declared on the source object and the deep validation rules will not be executed as there is nothing to validate against.

深層規則提供了直接一個定義嵌套規則的方式,讓你能夠簡化傳遞給 schema.validate()options

Deep rule validation creates a schema for the nested rules so you can also specify the `options` passed to the `schema.validate()` method.
var descriptor = {
  address: {
    type: "object", required: true, options: {single: true, first: 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}
}
var validator = new schema(descriptor);

validator.validate({ address: {} })
  .catch(({ errors, fields }) => {
    // now only errors for street and name    
  });

若是你像下面這樣寫,父規則也會被校驗

The parent rule is also validated so if you have a set of rules such as:
var descriptor = {
  roles: {
    type: "array", required: true, len: 3,
    fields: {
      0: {type: "string", required: true},
      1: {type: "string", required: true},
      2: {type: "string", required: true}
    }
  }
}

好比用於 {roles: ["admin", "user"]} 會產生兩個錯誤,一個是數組長度不匹配,一個是缺乏了索引爲 2 的元素

And supply a source object of `{roles: ["admin", "user"]}` then two errors will be created. One for the array length mismatch and one for the missing required array entry at index 2.

defaultField 默認字段

defaultField 屬性能夠在 arrayobject 類型中用於校驗全部的值,它能夠是一個包含有校驗規則的對象或數組。 例子以下:

The `defaultField` property can be used with the `array` or `object` type for validating all values of the container. It may be an `object` or `array` containing validation rules. For example:
var descriptor = {
  urls: {
    type: "array", required: true,
    defaultField: {type: "url"}
  }
}

注意,defaultFieldfields 的擴展,見 deep rules.

Note that `defaultField` is expanded to `fields`, see [deep rules](#deep-rules).

Transform 變換

有時候須要在校驗前修改值,強制修改成特定格式。 爲此在校驗規則中添加了 transform, 這個屬性會在校驗前執行,以適當的方式改變原始對象的值。(也就是返回值會做用在原始對象的值上)

Sometimes it is necessary to transform a value before validation, possibly to coerce the value or to sanitize it in some way. To do this add a `transform` function to the validation rule. The property is transformed prior to validation and re-assigned to the source object to mutate the value of the property in place.
var schema = require('async-validator');
var sanitize = require('validator').sanitize;
var descriptor = {
  name: {
    type: "string",
    required: true, pattern: /^[a-z]+$/,
    transform(value) {
      return sanitize(value).trim();
    }
  }
}
var validator = new schema(descriptor);
var source = {name: " user  "};
validator.validate(source)
  .then(() => assert.equal(source.name, "user"));

若是沒有 transform 函數校驗會失敗由於先後空格致使正則與輸入不符,但在添加了 transform 函數後即可經過由於字段已經被清洗了(或者翻譯爲使輸入值符合預期格式)

Without the `transform` function validation would fail due to the pattern not matching as the input contains leading and trailing whitespace, but by adding the transform function validation passes and the field value is sanitized at the same time.

Messages 提示信息

在某些需求下,你可能須要格式化支持或者想要不一樣校驗錯誤信息。

最簡單的方式就是直接爲 message 屬性賦值:

Depending upon your application requirements, you may need i18n support or you may prefer different validation error messages. The easiest way to achieve this is to assign a `message` to a rule:
{name:{type: "string", required: true, message: "Name is required"}}

消息能夠是任意類型的,好比 JSX

Message can be any type, such as jsx format.
{name:{type: "string", required: true, message: <b>Name is required</b>}}

也能夠是函數,好比使用 vue-i18n 時:

Message can also be a function, e.g. if you use vue-i18n:
{name:{type: "string", required: true, message: () => this.$t( 'name is required' )}}

有時候你只是須要對相同的校驗規則定義不一樣語言的提示信息,在這種狀況下爲各類語言重複定義信息就顯得不少餘。

你也能夠採起這個方案:定義你本身的提示信息並賦值給 schema

Potentially you may require the same schema validation rules for different languages, in which case duplicating the schema rules for each language does not make sense. In this scenario you could just provide your own messages for the language and assign it to the schema:
var schema = require('async-validator');
var cn = {
  required: '%s 必填',
};
var descriptor = {name:{type: "string", required: true}};
var validator = new schema(descriptor);
// deep merge with defaultMessages
validator.messages(cn);
...

若是你要定義本身的校驗函數,最好將提示信息賦值給消息對象,並在校驗函數中經過 options.messages 訪問消息。(說實話我沒看懂是什麼意思,應該是指不要把消息硬編碼寫在校驗函數裏面而是經過option傳遞,以便修改)

If you are defining your own validation functions it is better practice to assign the message strings to a messages object and then access the messages via the `options.messages` property within the validation function.

asyncValidator 異步校驗函數

你能夠對指定的字段自定義包含異步操做的校驗函數

You can customize the asynchronous validation function for the specified field:
const fields = {
  asyncField:{
    asyncValidator(rule,value,callback){
      ajax({
        url:'xx',
        value:value
      }).then(function(data){
        callback();
      },function(error){
        callback(new Error(error))
      });
    }
  },

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

validator 校驗函數

你也可像下面這樣自定義校驗函數:

you can custom validate function for specified field:
const fields = {
  field:{
    validator(rule,value,callback){
      return value === 'test';
    },
    message: 'Value is not equal to "test".',
  },

  field2:{
    validator(rule,value,callback){
      return new Error(`'${value} is not equal to "test".'`);
    },
  },
 
  arrField:{
    validator(rule, value){
      return [
        new Error('Message 1'),
        new Error('Message 2'),
      ];
    }
  },
};

FAQ

How to avoid warning 如何關閉警告

var Schema = require('async-validator');
Schema.warning = function(){};
相關文章
相關標籤/搜索