async-validator 的中文文檔翻譯


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

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

(大部分原因是我英文水平不夠,但是明明是中國人寫的為啥不順手寫個中文的 readme 呢,雖然就算翻譯成了中文也還是晦澀難懂。。。)

翻譯時間: 2019/5/31

正文開始。


async-validator

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

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

API

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

The following is modified from earlier version of [async-validate](https://github.com/freeformsystems/async-validate).

Usage 使用方法

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

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

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 對象:

  • 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 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(){};


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM