基於 Decorator 實現對象校驗

文章首發於 shuaizhang.topgit

Decorator 已經提案好久了,已經有過很大的改動。本文基於老的提案實現。es6

前言

有了 Decorator,我認爲表單校驗方式會有更多的玩法。因此基於 Decorator 實現了一個純淨的對象校驗的庫 dvalidator
在無任何校驗庫的幫助下,咱們可能會寫出這樣的代碼github

let form = {
  nickname: '',
  password: ''
}

function submit() {
  if (!checkNickName(form.nickname)) {
    alert('暱稱格式不正確')
    return
  }
  if (!checkPassword(form.password)) {
    alert('密碼格式不正確')
    return
  }

  remoteValid(form.nickname)
    .then(() => {
      // do next
    })
    .catch(() => {
      alert('暱稱已被註冊')
    })
}

使用 dvalidator 咱們能夠這樣寫npm

import dvalidator from 'dvalidator'

let form = {
  @dvalidator(remoteValid)('暱稱已被註冊')
  @dvalidator(checkNickName)('暱稱格式不正確')
  nickname: '',
  @dvalidator(checkPassword)('密碼格式不正確')
  password: ''
}

function submit() {
  form
    .$validate()
    .then(() => {
      // do next
    })
    .catch(error => alert(error[0].message))
}

Decorator 基礎

「裝飾者模式:在不改變原對象的基礎上,經過對其進行包裝拓展(添加屬性或者方法)使原有對象能夠知足用戶的更復雜需求。」
--《JavaScript 設計模式》
  1. 許多面向對象的語言都有修飾器(Decorator)函數,用來修改類的行爲
  2. 可做用於類或對象中的屬性和方法
  3. 初始化時從上至下運行,執行時從內向外

代碼來源: http://es6.ruanyifeng.com/#docs/decorator#%E6%96%B9%E6%B3%95%E7%9A%84%E4%BF%AE%E9%A5%B0設計模式

function dec(id){
  console.log('evaluated', id);
  return (target, property, descriptor) => console.log('executed', id);
}

class Example {
    @dec(1)
    @dec(2)
    method(){}
}
// evaluated 1
// evaluated 2
// executed 2
// executed 1

使用 dvalidator

使用 dvalidator 校驗對象有這些優勢bash

  1. 代碼更加直觀,優雅,便於後續維護
  2. 支持異步校驗:傳遞的校驗函數返回 Promise 便可實現
  3. 按順序校驗:根據 decorator 執行的前後順序

安裝

npm install dvalidator --save
npm install @babel/plugin-proposal-decorators --save-dev

使用

配置 babelbabel

plugins: [
  [
    '@babel/plugin-proposal-decorators',
    {
      legacy: true
    }
  ]
]

原理

  1. 爲對象增長 __rules 屬性,並不可枚舉,配置,寫
  2. rules的屬性與obj屬性一一對應
  3. 每申明一個Decorator,其實都是更新 __rules 屬性
  4. 調用 $validate 時,會根據 rules 對整個對象進行校驗,返回 Promise,校驗失敗會返回全部失敗信息

參考

相關文章
相關標籤/搜索