普通表单验证
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http:// xxx.com/register" id="registerForm" method="post">
请输入用户名:<input type="text" name="userName"/>
请输入密码:<input type="text" name="password"/>
请输入手机号码:<input type="text" name="phoneNumber"/>
<button>提交</button>
</form>
<script>
var registerForm = document.getElementById( 'registerForm' );
registerForm.onsubmit = function(){
if ( registerForm.userName.value === '' ){
alert ( '用户名不能为空' );
return false;
}
if ( registerForm.password.value.length < 6 ){
alert ( '密码长度不能少于 6 位' );
return false;
}
if ( !/(^1[3|5|8][0-9]{9}$)/.test( registerForm.phoneNumber.value ) ){
alert ( '手机号码格式不正确' );
return false;
}
}
</script>
</body>
</html>
缺点:
- registerForm.onsubmit 函数比较庞大,包含了很多 if-else 语句,这些语句需要覆盖所有
的校验规则。 - registerForm.onsubmit 函数缺乏弹性,如果增加了一种新的校验规则,或者想把密码的长 度校验从 6 改成8,我们都必须深入 registerForm.onsubmit 函数的内部实现,这是违反开 放—封闭原则的。
- 算法的复用性差,如果在程序中增加了另外一个表单,这个表单也需要进行一些类似的 校验,那我们很可能将这些校验逻辑复制得漫天遍野。
使用策略模式重构
策略模式指的是定义一系列的算法,把它们一个个封装起来。将不变的部分和变化的部分隔开是每个设计模式的主题,策略模式也不例外,策略模式的目的就是将算法的使用与算法的实现分离开来。
首先我们将校验逻辑封装成对象
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 ( !/(^1[3|5|8][0-9]{9}$)/.test( value ) ){
return errorMsg;
}
}
}
实现Validator函数
Validator其实就是将要验证的表单添加进去,然后进行校验,所以我们定义一个函数
存贮表单验证的函数,进行验证即可
//创建一个函数
var Validator = function(){
this.cache = []; // 保存校验规则
};
/**
* add
* dom dom节点
* rule:部分参数要求长度或者其他参数
* errorMsg:错误返回值
* */
Validator.prototype.add = function( dom, rule, errorMsg ){
//将有参数的数据分开 如 minLength:6 ===> [minLength,6] 么有的话就是一数组 [minLength]
var ary = rule.split( ':' );
//把校验的步骤用空函数包装起来,并且放入 cache
this.cache.push(function(){
//拿到当前要执行的函数名称
var strategy = ary.shift();
//拿到dom的值存到数组开头
ary.unshift( dom.value );
// 把 errorMsg 添加进参数列表
ary.push( errorMsg );
// 等待执行
return strategies[ strategy ].apply( dom, ary );
});
};
/**
* 执行验证
* 按顺序执行cache函数
* */
Validator.prototype.start = function(){
for ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){
var msg = validatorFunc(); // 开始校验,并取得校验后的返回信息
if ( msg ){ // 如果有确切的返回值,说明校验没有通过
return msg;
}
}
};
以上我们实现了校验函数的添加和验证
调用表单验证类
// Validator类
var validataFunc = function () {
var validator = new Validator() //创建一个 validator 对象3
//创建校验规则
validator.add( registerForm.userName, 'isNonEmpty', '用户名不能为空' );
validator.add( registerForm.password, 'minLength:6', '密码长度不能少于 6 位' );
validator.add( registerForm.phoneNumber, 'isMobile', '手机号码格式不正确' );
var errorMsg = validator.start(); // 获得校验结果
return errorMsg; // 返回校验结果
}
var registerForm = document.getElementById( 'registerForm' );
registerForm.onsubmit = function(){
var errorMsg = validataFunc(); // 如果 errorMsg 有确切的返回值,说明未通过校验
if ( errorMsg ){
alert ( errorMsg );
return false; // 阻止表单提交
}
};
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="http:// xxx.com/register" id="registerForm" method="post">
请输入用户名:<input type="text" name="userName"/>
请输入密码:<input type="text" name="password"/>
请输入手机号码:<input type="text" name="phoneNumber"/>
<button>提交</button>
</form>
<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 ( !/(^1[3|5|8][0-9]{9}$)/.test( value ) ){
return errorMsg;
}
}
}
// Validator类
var validataFunc = function () {
var validator = new Validator() //创建一个 validator 对象3
//创建校验规则
validator.add( registerForm.userName, 'isNonEmpty', '用户名不能为空' );
validator.add( registerForm.password, 'minLength:6', '密码长度不能少于 6 位' );
validator.add( registerForm.phoneNumber, 'isMobile', '手机号码格式不正确' );
var errorMsg = validator.start(); // 获得校验结果
return errorMsg; // 返回校验结果
}
var registerForm = document.getElementById( 'registerForm' );
registerForm.onsubmit = function(){
var errorMsg = validataFunc(); // 如果 errorMsg 有确切的返回值,说明未通过校验
if ( errorMsg ){
alert ( errorMsg );
return false; // 阻止表单提交
}
};
var Validator = function(){
this.cache = []; // 保存校验规则
};
/**
* 添加要验证的信息
* dom dom节点
* rule:部分参数要求长度
* errorMsg:错误返回值
* */
Validator.prototype.add = function( dom, rule, errorMsg ){
//将有参数的数据分开 如 minLength:6 ===> [minLength,6] 么有的话就是一数组 [minLength]
var ary = rule.split( ':' );
//把校验的步骤用空函数包装起来,并且放入 cache
this.cache.push(function(){
//拿到当前要执行的函数名称
var strategy = ary.shift();
//拿到dom的值存到数组开头
ary.unshift( dom.value );
// 把 errorMsg 添加进参数列表
ary.push( errorMsg );
// 等待执行
return strategies[ strategy ].apply( dom, ary );
});
};
/**
* 执行验证
* 按顺序执行cache函数
* */
Validator.prototype.start = function(){
for ( var i = 0, validatorFunc; validatorFunc = this.cache[ i++ ]; ){
var msg = validatorFunc(); // 开始校验,并取得校验后的返回信息
if ( msg ){ // 如果有确切的返回值,说明校验没有通过
return msg;
}
}
};
</script>
</body>
</html>