第一步:新建validatorRules.js,封装校验规则

import { PUBLICREG } from '@/utils/redisEnum'

const strategies = {
  isNotEmpty: function (value, typeName, errorMsg) {
    if (value === null || value === '' || value === 'undefined') {
      return errorMsg || (typeName ? `${typeName}不能为空` : '不能为空')
    }
  },
  minLength: function (value, length, errorMsg) {
    if (value.length < length) {
      return errorMsg || `至少输入${length}位字符`
    }
  },
  isMoblePhone: function (value, errorMsg) {
    if (!PUBLICREG.phoneReg.test(value)) {
      return errorMsg || '手机格式不合法'
    }
  },
  isUserName: function (value, errorMsg) {
    if (!PUBLICREG.userNameReg.test(value)) {
      return errorMsg || '姓名或昵称仅支持2-20位中文及字母'
    }
  },
  isIdCardNo: function (value, errorMsg) {
    if (!PUBLICREG.idCardReg.test(value)) {
      return errorMsg || '身份证格式不合法'
    }
  },
  isBankNo: function (value, errorMsg) {
    if (!PUBLICREG.bankNoReg.test(value)) {
      return errorMsg || '银行卡号格式不合法'
    }
  },
  isNumAndLetter: function (value, errorMsg) {
    if (!PUBLICREG.recomedReg.test(value)) {
      return errorMsg || '仅支持数字或字母组合'
    }
  }
}
export default strategies

第二步:新建validator.js,封装Validator,派发校验规则

import strategies from './validatorRules'

export default class Validator {
  constructor () {
    this.rules = []
  }

  add (value, rules) {
    for (const rule of rules) {
      // 取校验参数,例如 ['minLength', 6]
      const errorMsg = rule.errorMsg || null
      const ruleList = rule.strategy.split(':')

      this.rules.push(() => {
        const ruleKey = ruleList[0]
        ruleList.shift()
        ruleList.unshift(value)
        ruleList.push(errorMsg)
        return strategies[ruleKey].apply(null, ruleList)
      })
    }
  }

  run () {
    for (const validatorFunc of this.rules) {
      const errorMsg = validatorFunc()
      if (errorMsg) {
        return errorMsg
      }
    }
  },

  destory () {
    this.rules = []
  }
}

第三步:使用

import Validator from 'validator'
 
const validator = new Validator()
const firstRules = {userName: '', address: '', phone: ''}
 
validator.add(firstRules.userName, [{
  strategy: 'minLength:5',
  errorMsg: '至少输入5个字符'
}])

validator.add(firstRules.birthDate, [{
  strategy: 'isNoEmpty:出生日期'
}])
 
validator.add(firstRules.address, [{
  strategy: 'isNoEmpty:',
  errorMsg: '不能为空'
}, {
  strategy: 'minLength:10',
  errorMsg: '至少输入10个字符'  
}])
 
validator.add(firstRules.phone, [{
  strategy: 'isMoble',
  errorMsg: '手机格式不合法'
}])
 
const result = validator.run()
if (result) {
  alert(reslut)
  return false
}

缺点:

  1. 策略相互独立,因此一些复杂的算法逻辑无法共享,造成一些资源浪费;
  2. 如果用户想采用什么策略,必须了解策略的实现,因此所有策略都需向外暴露,这是违背迪米特法则/最少知识原则的,也增加了用户对策略对象的使用成本。

优点:

  1. 策略之间相互独立,但策略可以自由切换,这个策略模式的特点给策略模式带来很多灵活性,也提高了策略的复用率;
  2. 如果不采用策略模式,那么在选策略时一般会采用多重的条件判断,采用策略模式可以避免多重条件判断,增加可维护性;
  3. 可扩展性好,策略可以很方便的进行扩展;