表单校验优化(策略模式)

886 阅读2分钟

前言

之前写过表单校验的规则,翻回去看到的时候感觉逻辑不太清晰。希望能写一个扩展性好一些的校验,使用策略模式尝试修改一下。

策略模式

定义一系列的算法,然后把它们一个个的封装起来,这些封装起来的算法可以相互替换。

点击此处可查看全部代码

当点击提交时校验各必填项是否填写,并且(id,手机号等)需要添加各自额外的校验规则。

首先来实现每项不为空的校验,创建策略对象

const strategy = {
    hasValue(value, {errMsg}) {
      if (!value) {
        return errMsg
      }
   }
}
export const validatorValue = function validator(value, fnc, err) {
  return strategies[fnc](value, err)
}

通过核心思想是 将做什么和谁去做相分离管理函数负责指定策略对象下的具体的函数去执行。回到表单验证,每项需要验证的规则都不一样我们可以在策略对象下添加rule属性来规定每项校验的规则。

// 引入第三方插件负责校验返回Boolean值
import {isMobilePhone} from 'validator/index.js'
import {isValidID} from '../../../utils/identification'
// 校验策略类
const strategy = {
  handle: {
    hasValue(value, {errMsg}) {
      if (!value) {
        return errMsg
      }
    },
    minLength(value, {errMsg, param}) {
      if (value.length < param) {
        return errMsg
      }
    },
    isMobile(value, {errMsg}) {
      if (!isMobilePhone(value, ['zh-CN'])) {
        return errMsg
      }
    },
    isIdCard(value, {errMsg}) {
      console.log(value, 'value', isValidID(value, 'any'))
      if (!isValidID(value)) {
        return errMsg
      }
    }
  },
  rule: {
    agency: [
      {
        name: 'minLength',
        errMsg: '机构名称长度不能小于6位!',
        param: 6
      }
    ],
    code: [],
    legalName: [],
    id: [
      {
        name: 'isIdCard',
        errMsg: '请输入正确的身份证号'
      }
    ],
    contactName: [],
    phone: [
      {
        name: 'isMobile',
        errMsg: '请输入正确的手机号'
      }
    ],
    adrress: []
  }
}
// 给每项都设置为必填项
function require(rule, errMsg) {
  for (let type in rule) {
    rule[type].unshift({
      name: 'hasValue',
      errMsg: errMsg
    })
  }
}
/**
 * 对表单具体值进行校验,如有错误,返回错误信息
 * @param  {errMsg} 必填项的错误信息
 * @param  {validator} 策略类下的方法名
 * @return {value}  校验的值
 */
export const validatorValue = function (errMsg, validator, value) {
  // 给每项都添加必填规则
  require(strategy.rule, errMsg)
  const errList = strategy.rule[validator]

  // 校验规则
  for (let err of errList) {
    const result = strategy.handle[err.name](value, err)
    // 如果有值则返回第一个错误值
    if (result) {
      return result
    }
  }
}

// index.vue
import { validatorValue } from './strategy.js'
export default {
    methods:{
        checkInvalid() {
            const childrenList = this.$refs.group.$children
            for (let item of childrenList) {
            this.toastText = validatorValue(
              item.title.slice(1, -1) + '不能为空',
              item.name,
              item.currentValue
            )
            if (this.toastText) {
              break
            }
        }
    }
}

如果我们需要添加新的校验项,只需给校验项添加如 name="id" 然后在strategy.rule属性添加校验规则数组即可。

strategy{
    rule:{
        id:[
            {
                name: 'minLength',
                errMsg: 'id长度不能小于18位!',
                param: 18
            }
        ]
    }
}

小结

策略模式需要将环境类和 具体策略类分离开,提高了可读性和维护性。