背景
在最近做的一个项目当中,需要做到表单字段的校验,当用户输入的字段不符合要求时,提示错误信息。并且需要用户点击对应错的字段,错误提示才消失。(例如提示手机号错误,只能点击手机号输入框时,错误才消失)。
预览


在表单页面中,请求接口前前端都会做一些校验,例如输入不能为空、输入格式不正确等等。
1.传统方式if-else
在我的之前的版本实现当中,用的最多的是if-els(没有if-else判断不了的事情)。
if (!companyEmail) {
return false;
} else if (!companyPassword) {
return false;
}
If-else确实很方便就完成了们的需求,但是如果需要校验的字段不止两个,或者校验要求越来越多的话,用if-else就显得过于臃肿了,例如:
if (value1 == "") {
console.log("value1不能为空");
} else if (value1.length < 6) {
console.log("value1不能少于6位");
} else if (!(/'某正则'/.test(value1))) {
console.log("value1不符合规则");
}
光一个字段就已经有3个if-else了,如果字段多的话,这段if-else语句也会越来越长。
2.使用策略模式优化表单校验
js中的策略模式关键字:策略和业务分离
首先先定义一些我们验证的规则:
const strategies = {
/*判断是否为空*/
isNonEmpty([value, errorMsg]) {
return value == '' ?
errorMsg : ''
},
/*判断最小程度*/
minLength([value, length, errorMsg]) {
return value.length < length ?
errorMsg : ''
},
/*判断最大长度*/
maxLength([value, length, errorMsg]) {
return value.length > length ?
errorMsg : ''
},
/*判断是否手机号*/
isMoblie([value, errorMsg]) {
return !/^1(3|4|5|6|7|8|9)[0-9]{9}$/.test(value) ?
errorMsg : ''
},
/*判断邮箱号*/
isEmail([value, errorMsg]) {
return !/^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(value) ?
errorMsg : ''
},
......//其他验证规则
}
然后是Validator类的实现:
class Validator {
constructor() {
this.cache = [] //保存校验规则
}
add(ruleFiled, rules) {
let key = Object.keys(ruleFiled);//取出当前key值
let value = Object.values(ruleFiled);//取出当前value值
for (let rule of rules) {
let strategyAry = rule.strategy.split(':') //将strategy于参数分开,如minLength:6
let errorMsg = rule.errorMsg; //如:'用户名不能为空'
let strategy = strategyAry.shift() //取出strategy
strategyAry.unshift(value) //把value添加进参数列表
strategyAry.push(errorMsg) //把errorMsg添加进参数列表,[value,6,errorMsg]
let result = strategies[strategy](strategyAry)//要么返回errorMsg,要么返回''字符串
this.cache.push({ [key]: result });//根据当前key动态将一个对象存入校验规则数组当中,例如[{'telephone':'手机号错误,请重新输入'}]
}
}
start() {
let length = this.cache.length;
for (let index = 0; index < length; index++) {
const element = this.cache[index];//此时element是一个对象
const key = Object.keys(element);
//如果有确切返回值,说明校验没有通过
if (element[key]) {
//返回错误信息:{errorMsg: '手机号不能为空', errorType: telephone}
return { errorMsg: element[key], errorType: key }
}
}
}
}
add函数有两个参数,第一个是object,里面是当前验证的字段名以及value值,记录字段名是为了方便返回客户端当前出错的字段是哪个字段 如:{telephone:'1234567'}。第二个参数是需要校验的规则,例如客户端需要判断是否为空。通过this.cache保存了所有经过的之前定义的规则的结果。(每个验证的规则要么返回报错信息,要么返回空字符串)。
start函数用于启动遍历this.cache里面的值,如果判断里面元素的vue有确切值,说明校验不通过。
客户端调用代码如下:
import { Validator } from "./validator";
validator.add({ telephone }, [
{
strategy: "isNonEmpty",
errorMsg: "请输入手机号"
},
{
strategy: "isMoblie",
errorMsg: "手机号错误,请重新输入"
}
]);
Validator.js代码:
/*
* @Date: 2020-04-27 22:51:44
* @LastEditTime: 2020-04-29 15:53:24
*/
/*校验规则对象*/
const strategies = {
isNonEmpty([value, errorMsg]) {
return value == '' ?
errorMsg : ''
},
minLength([value, length, errorMsg]) {
return value.length < length ?
errorMsg : ''
},
maxLength([value, length, errorMsg]) {
return value.length > length ?
errorMsg : ''
},
isMoblie([value, errorMsg]) {
return !/^1(3|4|5|6|7|8|9)[0-9]{9}$/.test(value) ?
errorMsg : ''
},
isEmail([value, errorMsg]) {
return !/^\w+([+-.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/.test(value) ?
errorMsg : ''
}
}
/*Validator类*/
class Validator {
constructor() {
this.cache = [] //保存校验规则
}
add(ruleFiled, rules) {
let key = Object.keys(ruleFiled);//取出当前key值
let value = Object.values(ruleFiled);//取出当前value值
for (let rule of rules) {
let strategyAry = rule.strategy.split(':') //将strategy于参数分开,如minLength:6
let errorMsg = rule.errorMsg; //如:'用户名不能为空'
let strategy = strategyAry.shift() //取出strategy
strategyAry.unshift(value) //把value添加进参数列表
strategyAry.push(errorMsg) //把errorMsg添加进参数列表,[value,6,errorMsg]
let result = strategies[strategy](strategyAry)//要么返回errorMsg,要么返回''字符串
this.cache.push({ [key]: result });//根据当前key动态将一个对象存入校验规则数组当中,例如[{'telephone':'手机号错误,请重新输入'}]
}
}
start() {
let length = this.cache.length;
for (let index = 0; index < length; index++) {
const element = this.cache[index];//此时element是一个对象
const key = Object.keys(element);
//如果有确切返回值,说明校验没有通过
if (element[key]) {
//返回错误信息:{errorMsg: '手机号不能为空', errorType: telephone}
return { errorMsg: element[key], errorType: key }
}
}
}
}
export { Validator }
写在最后
代码基于很多篇文章的代码再结合自己的项目需求加了一部分代码,就不一一列出了。
当然,也需要结合实际需求,如果两三个if-else能解决的问题,就不用大刀阔斧的写各种方法了,显得杀鸡用宰牛刀的感觉。