js 策略模式实现大规模表单验证

我们在做页面开发的时候有时候会遇到一些比较多的表单页面,比如个人信息,企业信息,设备信息等,里面都是包含很多的字段,每个字段需要校验的规则其实是不一样的,这样我们在提交表单的时候页面要做校验工能怎么办呢?常规做法就是通过if 去判断,但是如果有几十个校验规则,那么代码不是有很多if else ? 维护起来是不是很头疼?

话不多说,现在就用策略模式去实现动态配置对应的校验规则,然后就可以轻松去实现对应表单的校验,后期维护代码也方便!

结果如下:

 原理就是将校验的方法抽离出来成为一个公共维护的对象,将对应的规则属性名跟对应数据的属性名相关联在一起,通过校验规则中的type 字段去找到对应检验规则方法,通过校验方法会返回对应的标识,不通过则会给出对应规则配置的错误提示语。

校验方法对象代码:

const checkFn = {
  // 为空校验
  required (v, reg = '', msg = '') {
    if (!v) {
      console.log(reg);
      Message.warning(msg);
      return false;
    }
    return true;
  },
  // 正则规则校验
  reg (v, reg, msg) {
    if (!reg.test(v)) {
      Message.warning(msg);
      return false;
    }
    return true;
  },
  // 长度校验
  length (v, reg = [0, 0], msg) {
    if (v.length < reg[0] || v.length > reg[1]) {
      Message.warning(msg);
      return false;
    }
    return true;
  }
  // 后面扩展的校验方法。。。。。
};

规则配置项目:

rules: {
        username: [
          {type: 'required',reg: '', errMsg: '用户必填'},
          {type: 'reg', reg: /(^[1-9]\d*$)/, errMsg: '用户必须时正整数'},
          {type: 'length', reg: [1, 5], errMsg: '用户长度必须在1~5位'}
        ],
        password: [
          {type: 'required', reg: '', errMsg: '密码必填'},
          {type: 'reg', reg: /[A-Za-z]+/, errMsg: '密码必须包含应该英文'},
          {type: 'length', reg: [3, 8], errMsg: '长度必须在3~8位'}
        ],
        email: [
          { type: 'required', reg: '', errMsg: '邮箱必填' },
          { type: 'reg', reg: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/, errMsg: '邮箱格式不正确' },
          { type: 'length', reg: [4, 9], errMsg: '邮箱长度必须在3~11位' }
        ],
        phone: [
          { type: 'required', reg: '', errMsg: '手机必填' },
          { type: 'reg', reg: /^1[3456789]\d{9}$/, errMsg: '手机格式不正确' },
          { type: 'length', reg: [1, 12], errMsg: '手机长度必须在11位' }
        ],
        cellphone: [
          { type: 'required', reg: '', errMsg: '电话必填' },
          { type: 'reg', reg: /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/, errMsg: '电话格式不正确' },
        ],
        address: [
          { type: 'required', reg: '', errMsg: '地址必填' },
          { type: 'length', reg: [1, 20], errMsg: '地址最长20位' }
        ],
        site: [
          { type: 'required', reg: '', errMsg: '网址必填' },
          { type: 'reg', reg: /^(https:\/\/|http:\/\/)/, errMsg: '网址格式不正确' }
        ],
      },

表单整体校验执行方法:

isPass () {
      for (let i in this.form) {
        let val = this.form[i]; // 值
        // 判断当前key是否有娇艳规则
        if (i in this.rules) {
          for (let k = 0; k < this.rules[i].length; k++) {
            let type = this.rules[i][k].type; // 执行校验类型
            let errMsg = this.rules[i][k].errMsg; // 执行校验类型
            let reg = this.rules[i][k].reg; // 执行校验类型
            let isTrue = checkFn[type](val, reg, errMsg);
            // 遇到第一个有校验规则不通过立即跳出函数
            if (!isTrue) {
              return isTrue;
            }
          }
        }
      }
      return true;
    },

整体代码:(ps: 用vue写的组件)

<template>
  <div class="login">
    <div class="content">
      <div class="right">
        <div class="box">
          <div class="title">
            <h2>表单校验</h2>
          </div>
          <div class="form">
            <div class="form-line">
              <el-input v-model="form.username" placeholder=" 用户名"></el-input>
            </div>
            <div class="form-line">
              <el-input type="password" v-model="form.password" placeholder=" 密码"></el-input>
            </div>
            <div class="form-line">
              <el-input v-model="form.email" placeholder=" 邮箱"></el-input>
            </div>
            <div class="form-line">
              <el-input v-model="form.phone" placeholder=" 手机"></el-input>
            </div>
            <div class="form-line">
              <el-input v-model="form.cellphone" placeholder=" 电话"></el-input>
            </div>
            <div class="form-line">
              <el-input v-model="form.address" placeholder=" 地址"></el-input>
            </div>
            <div class="form-line">
              <el-input v-model="form.site" placeholder=" 网址"></el-input>
            </div>
            <div class="form-line">
              <el-button type="primary" @click="login">登录</el-button>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { Message } from 'element-ui';
const checkFn = {
  // 为空校验
  required (v, reg = '', msg = '') {
    if (!v) {
      console.log(reg);
      Message.warning(msg);
      return false;
    }
    return true;
  },
  // 正则规则校验
  reg (v, reg, msg) {
    if (!reg.test(v)) {
      Message.warning(msg);
      return false;
    }
    return true;
  },
  // 长度校验
  length (v, reg = [0, 0], msg) {
    if (v.length < reg[0] || v.length > reg[1]) {
      Message.warning(msg);
      return false;
    }
    return true;
  }
  // 后面扩展的校验方法。。。。。
};
export default {
  name: 'App',
  data () {
    return {
      rules: {
        username: [
          {type: 'required',reg: '', errMsg: '用户必填'},
          {type: 'reg', reg: /(^[1-9]\d*$)/, errMsg: '用户必须时正整数'},
          {type: 'length', reg: [1, 5], errMsg: '用户长度必须在1~5位'}
        ],
        password: [
          {type: 'required', reg: '', errMsg: '密码必填'},
          {type: 'reg', reg: /[A-Za-z]+/, errMsg: '密码必须包含应该英文'},
          {type: 'length', reg: [3, 8], errMsg: '长度必须在3~8位'}
        ],
        email: [
          { type: 'required', reg: '', errMsg: '邮箱必填' },
          { type: 'reg', reg: /\w[-\w.+]*@([A-Za-z0-9][-A-Za-z0-9]+\.)+[A-Za-z]{2,14}/, errMsg: '邮箱格式不正确' },
          { type: 'length', reg: [4, 9], errMsg: '邮箱长度必须在3~11位' }
        ],
        phone: [
          { type: 'required', reg: '', errMsg: '手机必填' },
          { type: 'reg', reg: /^1[3456789]\d{9}$/, errMsg: '手机格式不正确' },
          { type: 'length', reg: [1, 12], errMsg: '手机长度必须在11位' }
        ],
        cellphone: [
          { type: 'required', reg: '', errMsg: '电话必填' },
          { type: 'reg', reg: /^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/, errMsg: '电话格式不正确' },
        ],
        address: [
          { type: 'required', reg: '', errMsg: '地址必填' },
          { type: 'length', reg: [1, 20], errMsg: '地址最长20位' }
        ],
        site: [
          { type: 'required', reg: '', errMsg: '网址必填' },
          { type: 'reg', reg: /^(https:\/\/|http:\/\/)/, errMsg: '网址格式不正确' }
        ],
      },
      form: {
        username: '',
        password: '',
        email: '',
        phone: '',
        cellphone: '',
        address: '',
        site: ''
      }
    };
  },
  methods: {
    isPass () {
      for (let i in this.form) {
        let val = this.form[i]; // 值
        // 判断当前key是否有娇艳规则
        if (i in this.rules) {
          for (let k = 0; k < this.rules[i].length; k++) {
            let type = this.rules[i][k].type; // 执行校验类型
            let errMsg = this.rules[i][k].errMsg; // 执行校验类型
            let reg = this.rules[i][k].reg; // 执行校验类型
            let isTrue = checkFn[type](val, reg, errMsg);
            // 遇到第一个有校验规则不通过立即跳出函数
            if (!isTrue) {
              return isTrue;
            }
          }
        }
      }
      return true;
    },
    login () {
      if (!this.isPass()) {
        return;
      } else {
        Message.success('校验通过');
      }
    }
  }
};
</script>
<style lang="scss">
.login {
  .el-button--primary {
    width: 100%;
  }
  .el-input__inner {
    margin-bottom: 20px;
    background: none;
    border:1px solid #ccc;
    color: #333;
    font-size: 15px;
  }
}
</style>
<style lang="scss" scoped>
#mainBox {
  height:auto !important;
}
.login {
  font-size: 0;
  height: calc(100vh);
  overflow: hidden;
  background: #2e344e;
  // background:url('/static/images/1.jpg');
  .content {
    width:1000px;
    height: 100vh;
    margin:0 auto;
    display:flex;
    justify-content: center;
    align-items: center;
  }
  .right {
    display: block;
    .box {
      width: 400px;
      margin:0 auto;
      padding: 30px;
      background:#fff;
    }
    .title {
      h2 {
        padding-bottom: 20px;
        font-size: 20px;
        color: #3399ff;
        text-align: center;
      }
    }
  }
}
</style>

猜你喜欢

转载自blog.csdn.net/CodingNoob/article/details/128037422
今日推荐