在一个 Web 项目中,注册、登录、修改用户信息等功能的实现都离不开提交表单。
在将用户输入的数据交给后台之前,常常要做一些客户端力所能及的校验工作,比如注册的时候需要校验是否填写了用户名,密码的长度是否符合规定,等等。这样可以避免因为提交不合法数据而带来的不必要网络开销。
主要解决了很多 冗余的 if-else 语句,提高了代码的复用性。
第一版:简单版本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form id="registerForm" method="POSt">
请输入用户名:<input type="text" id="userName">
请输入密码:<input type="text" id="password">
请输入手机号:<input type="text" id="phoneNumber">
</form>
<button id="button">提交</button>
</body>
<script>
// 公共校验数据模块,可以单独写一个文件并且抛出。
var strategies = {
isNonEmpty: function (value, errorMsg) { // 不为空
if (value === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) { // 限制最小长度
if (value.length < length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) { // 手机号码格式
if (!/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/.test(value)) {
return errorMsg;
}
}
};
class Validator {
constructor() {
this.arr = []
}
add(dom,rule,errorMsg) {
let ary = rule.split(':')
// 将每个 add 检验函数添加数组中进行统一执行
this.arr.push(function () {
// 按照 : 分割minLength参数 并且取出方法名字
let firstParams = ary.shift()
// 将表单的值追加第一个,对应校验方法的第一个参数
ary.unshift(dom.value)
// 将错误信息放到末尾
ary.push(errorMsg)
/**
* 这里使用apply就是为了在下面使用add 方法的时候进行调用并且传参数,并且修改了this指向,指向当前的输入框。第二的参数传入的一个数组,在上面的校验函数
* 每个参数就对应传进来的数组下标。
*/
return strategies[firstParams].apply(dom,ary)
})
}
start() {
// 统一执行校验方法并返回校验错误的信息。
for(let i = 0,validataFunc;validataFunc = this.arr[i++];) {
var msg = validataFunc()
if(msg) {
return msg
}
}
}
}
let registerForm = document.getElementById('registerForm');
button.onclick = function () {
var validator = new Validator(); // 创建一个 validator 对象
console.log(registerForm.userName);
validator.add(registerForm.userName, 'isNonEmpty', '用户名不能为空');
validator.add(registerForm.password, 'minLength:6', '密码长度不能少于 6 位');
validator.add(registerForm.phoneNumber, 'isMobile', '手机号码格式不正确');
var errorMsg = validator.start(); // 获得校验结果
if (errorMsg) {
alert(errorMsg);
return false; // 阻止表单提交
}
alert('通过校验')
};
</script>
</html>
第二版本基于函数扩展校验。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form id="registerForm" method="POSt">
请输入用户名:<input type="text" id="userName">
请输入密码:<input type="text" id="password">
请输入手机号:<input type="text" id="phoneNumber">
</form>
<button id="button">提交</button>
</body>
<script>
// 公共校验数据模块,可以单独写一个文件并且抛出。
var strategies = {
isNonEmpty: function (value, errorMsg) { // 不为空
if (value === '') {
return errorMsg;
}
},
minLength: function (value, length, errorMsg) { // 限制最小长度
if (value.length < length) {
return errorMsg;
}
},
isMobile: function (value, errorMsg) { // 手机号码格式
if (!/^(?:(?:\+|00)86)?1(?:(?:3[\d])|(?:4[5-79])|(?:5[0-35-9])|(?:6[5-7])|(?:7[0-8])|(?:8[\d])|(?:9[1589]))\d{8}$/.test(value)) {
return errorMsg;
}
}
};
class Validator {
constructor() {
this.arr = []
}
add(dom, rules,callBacks =[]) {
// 如果有自定义的校验循环并执行
if(callBacks.length) {
for (let i = 0, callBack; callBack = callBacks[i++];) {
// 如果想再在 start 函数中再次调用 arr 中的函数就必须,定义一个函数追加进去,然后返回一个基于 apply 调用的新函数方便二次执行。
this.arr.push(function() {
return callBack.apply(dom,[dom.value])
})
}
}
for (let i = 0, rule; rule = rules[i++];) {
let ary = rule.filed.split(':')
// 将每个 add 检验函数添加数组中进行统一执行
this.arr.push(function () {
// 按照 : 分割minLength参数 并且取出方法名字
let firstParams = ary.shift()
// 将表单的值追加第一个,对应校验方法的第一个参数
ary.unshift(dom.value)
// 将错误信息放到末尾
ary.push(rule.errMsg)
/**
* 这里使用apply就是为了在下面使用add 方法的时候进行调用并且传参数,并且修改了this指向,指向当前的输入框。第二的参数传入的一个数组,在上面的校验函数
* 每个参数就对应传进来的数组下标。
*/
return strategies[firstParams].apply(dom, ary)
})
}
}
start() {
// 统一执行校验方法并返回校验错误的信息。
for (let i = 0, validataFunc; validataFunc = this.arr[i++];) {
var msg = validataFunc()
if (msg) {
return msg
}
}
}
}
let formValidate = function () {
var validator = new Validator(); // 创建一个 validator 对象
console.log(registerForm.userName);
validator.add(registerForm.userName, [{
filed: 'isNonEmpty',
errMsg: '用户名不能为空'
}, {
filed: 'minLength:6',
errMsg: '用户名长度不能少于 6 位'
}]);
validator.add(registerForm.password, [{
filed: 'minLength:6',
errMsg: '密码长度不能少于 6 位'
}],[
function (value) {
console.log(this,'当前元素'); // 必须是 function 写法,箭头函数直接指向上一级,Window
if(value.length >= 14) {
return '密码长度不能大于 14 位'
}
}
]);
validator.add(
registerForm.phoneNumber,
[{
filed: 'isMobile',
errMsg: '手机号码格式不正确'
}],
[
(value) => {
if(value.length >= 12) {
return '手机号不能大于 12 位'
}
},
(value) => {
if(value == '') {
return '手机号不能为空'
}
},
]
);
return validator.start(); // 获得校验结果
}
button.onclick = function () {
let errorMsg = formValidate()
if (errorMsg) {
alert(errorMsg);
return false; // 阻止表单提交
}
alert('通过校验')
};
</script>
</html>