async-validator 原始碼學習(一):文件翻譯

前端人發表於2022-03-16

async-validator 是一個表單非同步校驗庫,阿里旗下的 Ant-design 和 Element 元件庫中的表單驗證使用的都是 async-validator ,目前版本已更新到 4.0.7 ,下載量達到 1,067,202次,不僅支援 js ,同時也可支援 typeScript 。是一個功能超級強大的庫,有興趣的一起來了解了解。

async-validator 官網地址:
https://www.npmjs.com/package/async-validator


async-validator 美中不足的是沒有中文官方文件,看著英文的好費勁!網上百度了一堆都是低版本的翻譯,現在升級到 4.0.7 了,有些效能廢棄了,會出現一些不起作用的屬性,所以今天幫大家也幫自己翻譯一下,便於學習。

一、從入門到上手

安裝命令

npm i async-validator
//
npm install async-validator

 

使用方法:

// 引入非同步
import Schema from 'async-validator'
// 定義規則描述
const des = {
 name: {
  type: "string",
  required: true,
  message: "內容不能為空"
 }
}
// 建立校驗器
const validator = new Schema(des)
// 新增校驗
validator.validate({ name: "值" }, (errors, field) => {
 if(errors){
  return new Error(`校驗失敗`)
 }
 // 校驗失敗
})

 

在 vue3 引入 Ant-design 元件中使用 async-validator ,使用例項:

<template>
 <div>
  <a-form style="width: 80%; margin: 0 auto;" :model="formData">
   <div>
     使用者名稱:
     <a-input type="text" @blur="check" v-model:value="formData.username"></a-input>
   </div>
   <div>
    密碼:
    <a-input type="passsword" v-model:value="formData.password"></a-input>
   </div>
   <a-button type="primary">提交</a-button>
  </a-form>
 </div>
</template>
<script lang="ts">
import { defineComponent, reactive, onMounted } from 'vue'
import Schema from 'async-validator'
interface IFormData {
 username: string
 password: string
}
export default defineComponent({
 setup() {
  const formData = reactive<IFormData>({
   username: '',
   password: '',
 })
 const des = {
  username: [
   {
    type: 'string',
    required: true,
    validator(rule, value) {
     return value != ''
    }
    message: '使用者名稱不能為空',
   },
   {
     type: 'string',
     min: 6,
     max: 10,
     validator(rule, value) {
       return rule.min < value.length && value.length < rule.max
      },
      message: '長度 6-8',
     },
    ],
  }
  const validator = new Schema(des)
  function check() {
   // 開始校驗
   validator.validate({ username: formData.username }, (errors, fields) => {
    if (errors) {
     return new Error(`不符合規則`)
    }
    console.log('校驗成功')
   }).then((res) => {
    console.log('res--->', res)
    })
  }
  return {
   formData,
   changeName,
  }
 }
})
</script>

 

Promise 使用方法

// 引入非同步
import Schema from 'async-validator'
// 定義規則描述
const des = {
 name: {
  type: "string",
  required: true,
  message: "內容不能為空",
  asyncValidator: (rule,value) => {
   // @rule 獲取到是此處限制規則
   // @value 獲取到屬性 name 的值
   return new Promise((resolve,reject) => {
    setTimeout(()=>{ // 使用定時器模擬非同步操作
    if(value != ""){
     resolve() //成功
    }else{
     reject("校驗失敗")
    }
    },2000)
   })
  }
 }
}
// 建立校驗器
const validator = new Schema(des)
// 新增校驗
validator.validate({ name: "值" }, (errors, field) => {
}).then(() => {
 console.log('校驗成功')
}).catch(({ errors, fields } => {
  console.log('校驗失敗', errors)
}))

 

使用方法挺簡單的,可以根據上述的例項進行簡單修改就可以實現,也可以自己動手試試!

二、API 學習

2.1、validate

validate:新增校驗的方法,使用語法:

validator.validate( source , [options], callback ): Promise
  • source 是需要校驗的屬性和值,必傳引數。
  • options 是描述處理驗證物件的選項。
  • callback 校驗完成之後的回撥函式。

該方法返回的是 Promise 物件,所以有:

  • then() 成功回撥
  • catch(({ errors, fields })=>{}) 失敗回撥

Options 選項引數有:

  • suppressWarning:是一個 Boolean 值,是否抑制無效的內部警告。
  • first:是一個 Boolean 值,當第一個校驗失敗時,是否繼續向後校驗,如果為真,只返回第一個校驗失敗資訊。
  • firstFields:是一個 Boolean 值或 字串陣列,當指定的第一個校驗規則生成錯誤時呼叫回撥,不再處理同一欄位的驗證規則,true 表示所有欄位。

2.2、Rules

rules :表示校驗規則,通常有兩種寫法:

第一種:經常寫成一個物件陣列,便於給單個欄位新增多個驗證規則。使用如下:

const descriptor = {
 name:[
  {
    type: 'string',
    required: true,
    validator(rule, value) {
     return value != ''
    }
    message: '使用者名稱不能為空',
   },
   {
     type: 'string',
     min: 3,
     max: 8,
     validator(rule, value) {
      return rule.min < value.length && value.length < rule.max
     },
    message: '使用者名稱長度 3-8',
   },
 ]
}

 

第二種:也可以定義成執行驗證的函式,使用語法:

function (rule, value, callback, source, options)
  • rule 是源描述符中與正在驗證的欄位名相對應的驗證規則,始終會為其分配一個欄位屬性,該屬性包含要驗證的欄位名稱
  • value 是校驗屬性的值。
  • callback 呼叫完成後呼叫的回撥函式。
  • source 校驗的源物件。
  • options 其他選項。

傳遞給 validate 或 asyncValidate 的選項將傳遞給驗證函式,以便您可以在驗證函式中引用瞬態資料(例如模型引用)。但是,保留了一些選項名稱;如果使用選項物件的這些屬性,它們將被覆蓋。保留屬性包括訊息、異常和錯誤。

2.3、Type

type :指示要校驗的屬性型別,它的型別值有:

  • string - 預設值,屬性型別必須是字串。
  • number - 必須是數字。
  • boolean - 是布林值。
  • regexp - 是一個 RegExp 例項或 new RegExp 時不生成異常字串
  • method - 必須是一個函式。
  • integer - 必須是數字和整數型別。
  • float - 必須是數字和浮點數。
  • array - 是陣列,使用 Array.isArray 驗證。
  • object - 是一個物件而且不是陣列物件。
  • enum - 值必須存在於列舉中。
  • date - 值必須是由日期確定的有效值。
  • url - 是一個 url 型別。
  • hex - 十六進位制。
  • email - 必須是 email 型別。
  • any - 可以為任意型別。

2.4、Required

required 屬性代表源物件上必須存在該欄位。

2.5、Pattern

rule 屬性指示必須匹配正規表示式。

2.6、Range

通過使用 min(最小) 和 max(最大) 屬性定義一個範圍,對應字串和陣列會與 length 比較,對於數字會直接拿值比較。

2.7、Length

會使用 len 屬性定義長度,對應字串和陣列會與 length 比較,數字會直接拿值進行比較。如果 min、max 和 len 同時出現時,len 優先使用。

2.9、Enumerable

enumerable 可列舉值。對於可以列舉出所有情況的型別,可使用列舉校驗,如:

var descriptor = {
  role: {type: "enum", enum: ['admin', 'user', 'guest']}
}

2.10、Whitespace

通常將僅包含空格的必填欄位視為錯誤。要為僅由空格組成的字串新增附加測試,請將whitespace屬性新增到值為true. 規則必須是string型別。

您可能希望清理使用者輸入而不是測試空格,請參閱 transform 以獲取允許您去除空格的示例。

個人使用 whitespace 之後,感覺沒有任何影響,官方講的也很簡單,未找到具體例項,如果有會用的,還請不吝賜教。

2.11、Deep Rules

如果需要校驗的資料型別是物件,且需要校驗物件中的每一個屬性,此時需要通過巢狀規則分配給 rules 的 fields 屬性來校驗屬於 object 或 array 型別的校驗規則。

對 object 的深度監聽:

const rules = {
 address: {
 type: 'object',
 required: true,
 fields: {
  street: { type: 'string', required: true },
  city: { type: 'string', required: true }
  }
 }
}

 

注意:如果在父規則上沒有指定 required 屬性,此時沒有在源物件上宣告的欄位也是有效的,但是深度監聽會失效。

對 array 的深度監聽:

const 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'] } 這樣的 source 物件,將建立兩個錯誤。一個用於陣列長度不匹配,另一個用於缺少索引 2 處所需的陣列。

2.12、defaultField

defaultField 屬性用來校驗內部的所有值,可以用於 array 或 object 型別。

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

 

注意,若將 defaultField 擴充套件為fields,請參見 deep rules。

2.13、transform

有時校驗之前需要進行某種處理或者轉化,因此在校驗規則中新增 transform 函式,在校驗之前對屬性進行某種轉換,並重新分配給源物件以更改屬性的值。

const rules = {
 username: {
  type: 'string',
   required: true,
   pattern: /^[a-z]+$/,
   transform(value) {
    return value.trim();
   },
 },
}
const validator = new Schema(rules)
const source = { username: ' user  ' };
validator.validate(source).then(() => assert.equal(source.name, 'user'));

 

transform 函式內的 value.trim() 會把傳入的值前後空格去掉,所以校驗成功,如果沒有 transfrom 函式,校驗將會失敗。

2.14、message

根據應用的需求,可能需要 i18n 支援,或者您可能更喜歡不同的驗證錯誤訊息。

最簡單的方法給 rule 分配一條 message 屬性:

const rules = {
 username: {
  type: 'string',
  required: true,
  message:"使用者名稱不能為空" 
 }
}

 

message 可以是任意型別,如 jsx 格式:

const rules = {
 username: {
  type: 'string',
  required: true,
  message:"<b>使用者名稱不能為空</b>" 
 },
}

 

message 也可以是一個函式,比如 vue-i18n :

{ name: { type: 'string', required: true, message: () => this.$t( '請填寫名稱' ) } }

 

不同語言可能需要相同的模式驗證規則,在這種情況下,為每種語言複製模式規則是沒有意義的。

在這種情況下,您可以為該語言提供自己的訊息,並將其分配給 shema:

import Schema from 'async-validator';
const cn = {
  required: '%s 必填',
};
const descriptor = { name: { type: 'string', required: true } };
const validator = new Schema(descriptor);
// deep merge with defaultMessages
validator.messages(cn);

 

如果要定義自己的驗證函式,最好將訊息字串指定給messages物件,然後通過選項訪問訊息。驗證函式中的messages屬性。

2.15、asyncValidator

為指定欄位自定義非同步校驗函式:

const rules = {
 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)
  })
 },
 ],
}
const validator = new Schema(rules)
const source = { username: ' user  ' };
validator.validate(source).then((res) => {
 console.log('res', res)
})
.catch(({ errors, fields }) => {
 console.log('err', errors)
 console.log('fields', fields)
})

 

2.16、validator

為指定欄位自定義同步校驗函式:

const rules = {
 username: [
  {
   type: 'string',
   required: true,
   validator(rule, value) {
    return value != ''
    },
    message: '使用者名稱不能為空',
   },
   {
    type: 'string',
    min: 6,
    max: 10,
    validator(rule, value) {
      return rule.min < value.length && value.length < rule.max
     },
     message: '長度 6-8',
   },
 ],
}

 

常見問題

如何取消 warning

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

 

如果檢查布林值true

使用 enum 型別 並傳佈爾值 true 引數作為選項。

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

 

測試用例

npm test

測試覆蓋率

npm run coverage

相關文章