從0開始,編寫一個驗證函數(工具函數)

  • 爲何要寫驗證函數
  • 將驗證過程變成多個步驟
  • 完成一個基本的驗證函數

1. 爲何要寫驗證函數

以前寫項目的時候,通常都是在登陸註冊,修改密碼的時候有須要些正則的需求,因此每次用到的時候都是直接從前面的代碼copy過去就行了,直到後臺開始寫後臺管理系統類的項目,複製粘貼已經徹底不可行了。怎麼能作一個只會ctrl+c,ctrl+v的程序猿呢!簡直不能忍,因而就想到了本身寫一個驗證函數,每次須要作驗證的時候只須要調用這個函數,傳入參數就能夠了,想一想都美滋滋。git


2. 將驗證過程變成多個步驟


作驗證的時候咱們要作的,定義驗證失敗後的提示,編寫驗證的方法,而後調用驗證獲得結果。 一個驗證的過程,通常即是分爲這幾步,咱們能夠按照這個步驟設計出本身的驗證函數。github

var validatorObj = {
    // 驗證定義
    validator: {
        // 驗證失敗後的提示
        messages: {},
        // 驗證的方法, 返回一個布爾值
        methods: {}
    },
    // 獲得驗證結果
    checkResult: {}
}
複製代碼

定義一些驗證失敗的提示

定義的錯誤提示能夠自定義,至於{0} {1}等則是用來作一個標識符,在驗證失敗後會將要驗證的參數替換掉標識符數組

// 驗證失敗後的提示
messages: {
        notnull: '請輸入{0}',
        max: '長度最多爲 {1} 個字符',
        min: '長度最小爲 {1} 個字符',
        length: '{0}的長度在 {1} 到 {2} 個字符',
        number: '{0}必須是數字',
        string: '{0}必須是字母或者數字',
        moblie: '{0}必須是手機或者電話號碼格式',
        noChinese: '{0}不能爲中文',
        lon: '{0}範圍爲-180.0~+180.0(必須輸入1到10位小數)',
        lat: '{0}範圍爲-90.0~+90.0(必須輸入1到10位小數)',
        url: '請輸入正確的{0}訪問地址',
        repeat: '兩次輸入的{0}不一致',
        email: '郵箱格式不正確',
        password: '請輸入由大小寫字母+數字組成的6-16位密碼',
        fixedNum: '請輸入{1}位數字'
      }
複製代碼

定義對應的驗證方法

能夠看到幾乎在每一個驗證前面都加了一個當數據爲空的時候,返回爲true,這是由於有的時候咱們並不關心某一個數據是否填寫,但一旦填寫了,又要求符合某種規則。因此若是要驗證非空的時候,須要使用兩個驗證屬性。bash

// 驗證的方法, 返回一個布爾值
methods: {
        notnull: obj => {
          return obj.value || obj.value === 0
        },
        max: obj => {
          if (!obj.value) return true
          return obj.conditions[0] >= obj.value.length
        },
        min: obj => {
          if (!obj.value) return true
          return obj.value.length >= obj.conditions[0]
        },
        length: obj => {
          if (!obj.value) return true
          return obj.conditions[0] <= obj.value.length && obj.value.length <= obj.conditions[1]
        },
        number: obj => {
          if (!obj.value) return true
          reg = /^[0-9]+.?[0-9]*$/
          return reg.test(obj.value)
        },
        string: obj => {
          if (!obj.value) return true
          reg = /^[a-zA-Z0-9]+$/
          return reg.test(obj.value)
        },
        moblie: obj => {
          if (!obj.value) return true
          reg = /^(1[3,5,8,7]{1}[\d]{9})|(((400)-(\d{3})-(\d{4}))|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{3,7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)$/
          return reg.test(obj.value)
        },
        noChinese: obj => {
          if (!obj.value) return true
          reg = /[\u4e00-\u9fa5]/
          return !reg.test(obj.value)
        },
        lon: obj => {
          if (!obj.value) return true
          reg = /^[\-\+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,10}|180\.0{1,10})$/
          return reg.test(obj.value)
        },
        lat: obj => {
          if (!obj.value) return true
          reg = /^[\-\+]?([0-8]?\d{1}\.\d{1,10}|90\.0{1,10})$/
          return reg.test(obj.value)
        },
        url: obj => {
          if (!obj.value) return true
          reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/
          return reg.test(obj.value)
        },
        repeat: obj => {
          if (!obj.value) return true
          return obj.value === obj.value1
        },
        email: obj => {
          if (!obj.value) return true
          reg = /^([-_A-Za-z0-9\.]+)@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,3}$/
          return reg.test(obj.value)
        },
        password: obj => {
          if (!obj.value) return true
          reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z\d]{6,16}$/
          return reg.test(obj.value)
        },
        fixedNum: obj => {
          if (!obj.value) return true
          return obj.value.length === obj.conditions[0]
        }
      }
複製代碼

調用驗證方法

這裏是調用驗證函數的方法,和上面的定義結合起來。 傳入要驗證的規則,驗證的值,驗證的字段名字,若是有條件則加上條件數組(條件數組是須要咱們本身去設計的)微信

/**
 1.  傳入驗證規則,獲得驗證結果
 2.  @param {Obj} { label, value, rules, conditions}
 3.  @param {String} label: 驗證的字段名稱
 4.  @param {String} value: 驗證的值 (驗證重複的時候能夠添加value1屬性)
 5.  @param {Array} rules: 驗證的規則數組 例如: ['notnull', 'length'] 若是參數必填,第一個參數爲notnull
 6.  @param {Array} conditions: 條件字段 例如: ['2', '10'] ,則驗證長度錯誤會提示: 密碼的長度在2到10個字符,以傳入數組的條件去作驗證, 驗證的提示{1}開始將匹配的是當前數組
 7.  @return {obj} { result, message } 驗證結果對象
 */
// 獲得驗證結果
checkResult: function (obj) {
      let result = true,
          checkType, 
          message = '驗證成功',
          validatorMethods = this.validator.methods,
          validatorMessage = this.validator.messages
      // 循環驗證
      for (let i = 0, len = obj.rules.length; i < len; i++) {
        // 當驗證的規則不存在,默認跳過這個驗證
        if (!validatorMethods[obj.rules[i]]) {
          console.log(obj.rules[i] + '規則不存在')
          break
        }
        // 獲得當前驗證失敗信息
        if (!validatorMethods[obj.rules[i]](obj)) {
          checkType = obj.rules[i]
          result = false
          break
        }
      }
      // 若是驗證失敗, 獲得驗證失敗的結果集
      if (!result) {
        message = validatorMessage[checkType]
        if (obj.conditions) {
          obj.conditions.forEach((item, index) => {
            message = message.replace('{' + (index + 1) + '}', item)
          })
        }
        message = message.replace('{0}', obj.label)
        return {result, message}
      }

      return {result, message}
    }
複製代碼

3. 完整的驗證函數

把上面的步驟拼在一塊兒,就能夠完成一個驗證函數。具體的需求和使用,能夠根據項目自定義,但思路大體是這樣的。函數

/**
 * 傳入驗證規則,獲得驗證結果
 * @param {Obj} { label, value, rules, conditions}
 *  @param {String} label: 驗證的字段名稱
 *  @param {String} value: 驗證的值 (驗證重複的時候能夠添加value1屬性)
 *  @param {Array} rules: 驗證的規則數組 例如: ['notnull', 'length'] 若是參數必填,第一個參數爲notnull
 *  @param {Array} conditions: 條件字段 例如: ['2', '10'] ,則驗證長度錯誤會提示: 密碼的長度在2到10個字符,以傳入數組的條件去作驗證, 驗證的提示{1}開始將匹配的是當前數組
 * @return {obj} { result, message } 驗證結果對象
 */
function validate (obj) {
  let reg
  const validatorObj = {
    // 驗證定義
    validator: {
      // 驗證失敗後的提示
      messages: {
        notnull: '請輸入{0}',
        max: '長度最多爲 {1} 個字符',
        min: '長度最小爲 {1} 個字符',
        length: '{0}的長度在 {1} 到 {2} 個字符',
        number: '{0}必須是數字',
        string: '{0}必須是字母或者數字',
        moblie: '{0}必須是手機或者電話號碼格式',
        noChinese: '{0}不能爲中文',
        lon: '{0}範圍爲-180.0~+180.0(必須輸入1到10位小數)',
        lat: '{0}範圍爲-90.0~+90.0(必須輸入1到10位小數)',
        url: '請輸入正確的{0}訪問地址',
        repeat: '兩次輸入的{0}不一致',
        email: '郵箱格式不正確',
        password: '請輸入由大小寫字母+數字組成的6-16位密碼',
        fixedNum: '請輸入{1}位數字'
      },
      // 驗證的方法, 返回一個布爾值
      methods: {
        notnull: obj => {
          return obj.value || obj.value === 0
        },
        max: obj => {
          if (!obj.value) return true
          return obj.conditions[0] >= obj.value.length
        },
        min: obj => {
          if (!obj.value) return true
          return obj.value.length >= obj.conditions[0]
        },
        length: obj => {
          if (!obj.value) return true
          return obj.conditions[0] <= obj.value.length && obj.value.length <= obj.conditions[1]
        },
        number: obj => {
          if (!obj.value) return true
          reg = /^[0-9]+.?[0-9]*$/
          return reg.test(obj.value)
        },
        string: obj => {
          if (!obj.value) return true
          reg = /^[a-zA-Z0-9]+$/
          return reg.test(obj.value)
        },
        moblie: obj => {
          if (!obj.value) return true
          reg = /^(1[3,5,8,7]{1}[\d]{9})|(((400)-(\d{3})-(\d{4}))|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{3,7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$)$/
          return reg.test(obj.value)
        },
        noChinese: obj => {
          if (!obj.value) return true
          reg = /[\u4e00-\u9fa5]/
          return !reg.test(obj.value)
        },
        lon: obj => {
          if (!obj.value) return true
          reg = /^[\-\+]?(0?\d{1,2}\.\d{1,5}|1[0-7]?\d{1}\.\d{1,10}|180\.0{1,10})$/
          return reg.test(obj.value)
        },
        lat: obj => {
          if (!obj.value) return true
          reg = /^[\-\+]?([0-8]?\d{1}\.\d{1,10}|90\.0{1,10})$/
          return reg.test(obj.value)
        },
        url: obj => {
          if (!obj.value) return true
          reg = /^([hH][tT]{2}[pP]:\/\/|[hH][tT]{2}[pP][sS]:\/\/)(([A-Za-z0-9-~]+)\.)+([A-Za-z0-9-~\/])+$/
          return reg.test(obj.value)
        },
        repeat: obj => {
          if (!obj.value) return true
          return obj.value === obj.value1
        },
        email: obj => {
          if (!obj.value) return true
          reg = /^([-_A-Za-z0-9\.]+)@([_A-Za-z0-9]+\.)+[A-Za-z0-9]{2,3}$/
          return reg.test(obj.value)
        },
        password: obj => {
          if (!obj.value) return true
          reg = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])[a-zA-Z\d]{6,16}$/
          return reg.test(obj.value)
        },
        fixedNum: obj => {
          if (!obj.value) return true
          return obj.value.length === obj.conditions[0]
        }
      }
    },
    // 獲得驗證結果
    checkResult: function (obj) {
      let result = true,
          checkType, 
          message = '驗證成功',
          validatorMethods = this.validator.methods,
          validatorMessage = this.validator.messages
      // 循環驗證
      for (let i = 0, len = obj.rules.length; i < len; i++) {
        // 獲得當前驗證失敗信息
        if (!validatorMethods[obj.rules[i]](obj)) {
          checkType = obj.rules[i]
          result = false
          break
        }
      }
      // 若是驗證失敗, 獲得驗證失敗的結果集
      if (!result) {
        message = validatorMessage[checkType]
        if (obj.conditions) {
          obj.conditions.forEach((item, index) => {
            message = message.replace('{' + (index + 1) + '}', item)
          })
        }
        message = message.replace('{0}', obj.label)
        return {result, message}
      }

      return {result, message}
    }
  }
  return validatorObj.checkResult(obj)
}

export default validate

複製代碼

使用示例

validate({label: 'username', value: 'admin', rules: ['notnull', 'length'], conditions: ['2', '10']}) // 驗證username不爲空且長度在2-10之間
validate({label: 'pawwword', value: 'lllyh111', rules: ['notnull', 'password']}) // 驗證password由大小寫字母+數字組成的6-16位密碼
複製代碼

驗證返回結果大概長這樣:ui

{result: true, message: '驗證成功'}
{result: false, message: '驗證失敗提示'}
複製代碼

4.在頁面上的使用

把函數放在全局,須要作驗證的地方直接調用這個函數就ojbk了。this

在Elementui中的例子

// 檢測號碼
    const checkMobile = (rule, value, callback) => {
      let check = this.$validate({label: '號碼', value, rules: ['moblie']})
      if (!check.result) {
        callback(new Error(check.message))
      } else {
        callback()
      }
    }
    // 檢測非中文
    const checkWechat = (rule, value, callback) => {
      let check = this.$validate({label: '微信', value, rules: ['noChinese', 'max'], conditions: [12]})
      if (!check.result) {
        callback(new Error(check.message))
      } else {
        callback()
      }
    }
複製代碼

源碼---如何使用url

頁面效果--登陸-系統管理-用戶管理中可看到相關驗證效果spa

相關文章
相關標籤/搜索