我们在做页面开发的时候有时候会遇到一些比较多的表单页面,比如个人信息,企业信息,设备信息等,里面都是包含很多的字段,每个字段需要校验的规则其实是不一样的,这样我们在提交表单的时候页面要做校验工能怎么办呢?常规做法就是通过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>