手把手教你自己写一个js表单验证框架的方法


Posted in Javascript onSeptember 14, 2010

在表单程序中,在页面上需要很多的Js代码来验证表单,每一个field是否必须填写,是否
只能是数字,是否需要ajax到远程验证,blablabla。
如果一个一个单独写势必非常的繁琐,所以我们的第一个目标就是构建一个类似DSL的东西,
用表述的语句而非控制语句来实现验证。
其次一个个单独写的话还有一个问题就是必须全部验证通过才能提交,但是单独验证会因为
这个特征而增加很多额外的控制代码,且经常会验证不全面。所以第二个目标就是能够全面
的整合整个验证的过程。
最后不能是一个无法扩展的一切写死的实现,必要的扩展性还是要的。
首先,我们需要一个能够描述对字段验证的类

function Field(params){ 
this.field_id=params.fid; //要验证的字段的ID 
this.validators=params.val; //验证器对象数组 
this.on_suc=params.suc; //当验证成功的时候执行的事件 
this.on_error=params.err; //当验证失败的时候执行的事件 
this.checked=false; //是否通过验证 
}

关于验证器对象我们在后面来讨论,接下来我们扩展这个类,加入validate方法
Field.prototype.validate=function(){ 
//循环每一个验证器 
for(item in this.validators){ 
//给验证器附加验证成功和验证失败的回调事件 
this.set_callback(this.validators[item]); 
//执行验证器上的Validate方法,验证是否符合规则 
if(!this.validators[item].validate(this.data())){ 
break; //一旦任意一个验证器失败就停止 
} 
} 
}

再加入一个获取字段值的方法:
//获取字段值的方法 
Field.prototype.data=function(){ 
return document.getElementById(this.field_id).value; 
}

设置验证器回调函数的方法set_callback如下:
Field.prototype.set_callback=function(val){ 
var self=this; //换一个名字来存储this,不然函数的闭包中会覆盖这个名字 
val.on_suc=function(){ //验证成功执行的方法 
self.checked=true; //将字段设置为验证成功 
self.on_suc(val.tips); //执行验证成功的事件 
} 
val.on_error=function(){ //验证失败的时候执行的方法 
self.checked=false; //字段设置为验证失败 
self.on_error(val.tips);//执行验证失败的事件 
} 
}

接下来我们就来看看验证器,验证器是真正执行验证过程的类,根据一般的验证过程,我们
可以将其分类成,长度验证(包括必填验证),正则表达式验证,自定义函数验证,Ajax远
程验证这几种,所以我们定义这几种验证器类,Ajax远程验证为了方便引用了jQuery,其他
部分也有用到:

//长度验证的验证器类 
function Len_val(min_l,max_l,tip){ 
this.min_v=min_l; 
this.max_v=max_l; 
this.tips=tip; 
this.on_suc=null; 
this.on_error=null; 
} 
Len_val.prototype.validate=function(fd){ 
if(fd.length<this.min_v||fd.length>this.max_v){ 
this.on_error(); 
return false; 
} 
this.on_suc(); 
return true; 
} 
//正则表达式验证器 
function Exp_val(expresion,tip){ 
this.exps=expresion; 
this.tips=tip; 
this.on_suc=null; 
this.on_error=null; 
} 
Exp_val.prototype.validate=function(fd){ 
if(!fd){ 
this.on_suc(); 
return true; 
} 
if(this.exps.test(fd)){ 
this.on_suc(); 
return true; 
}else{ 
this.on_error(); 
return false; 
} 
} 
//远程验证器 
function Remote_val(url,tip){ 
this.p_url=url; 
this.tips=tip; 
this.on_suc=null; 
this.on_error=null; 
} 
Remote_val.prototype.validate=function(fd){ 
var self=this; 
$.post(this.p_url,{f:fd}, 
function(data){ 
if(data.rs){ 
self.on_suc(); 
return; 
}else{ 
self.on_error(); 
} 
},"json" 
); 
return false; 
} 
//自定义函数验证器 
function Man_val(tip,func){ 
this.tips=tip; 
this.val_func=func; 
this.on_suc=null; 
this.on_error=null; 
} 
Man_val.prototype.validate=function(fd){ 
if(this.val_func(fd)){ 
this.on_suc(); 
}else{ 
this.on_error(); 
} 
}

最后我们用一个userform的类来做一个入口,在构造的时候传入Field对象的列表,并且将
每一个控件的onblur事件绑定到validate的包装器上
function UserForm(items){ 
this.f_item=items; //把字段验证对象数组复制给属性 
for(idx=0;idx<this.f_item.length;idx++){ //循环数组 
var fc=this.get_check(this.f_item[idx]); //获取封装后的回调事件 
$("#"+this.f_item[idx].field_id).blur(fc); //绑定到控件上 
} 
} 
//绑定验证事件的处理器,为了避开循环对闭包的影响 
UserForm.prototype.get_check=function(v){ 
return function(){ //返回包装了调用validate方法的事件 
v.validate(); 
} 
}

接下来需要定义一个方法来绑定提交按钮的onclick事件:
//绑定提交事件到元件 
UserForm.prototype.set_submit=function(bid,bind){ 
var self=this; 
$("#"+bid).click( 
function(){ 
if(self.validate()){ 
bind(); 
} 
} 
); 
}

这里提到了一个UserForm的validate方法,如下:
//验证所有的字段 
UserForm.prototype.validate=function(){ 
for(idx in this.f_item){ //循环每一个验证器 
this.f_item[idx].validate(); //再检测一遍 
if(!this.f_item[idx].checked){ 
return false; //如果错误就返回失败,阻止提交 
} 
} 
return true; //一个都没错就返回成功执行提交 
}

最后用一个例子来看看怎么用:

<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> 
<title>test</title> 
<script type="text/javascript" src="jquery-1.4.2.min.js"></script> 
<script type="text/javascript" src="kernel.js"></script> 
<script type="text/javascript"> 
var form; 
$( 
function(){ 
var uf=new UserForm([new Field({ 
fid:"f1", 
val:[new Len_val(1,5,"长度错误"),new Exp_val(v_int,"不是数字")], 
suc:function(text){ 
$('t1').val(''); 
$('t1').attr('class','suc'); 
}, 
err:function(text){ 
('t1').val(text); 
$('t1').attr('class','error'); 
} 
}) 
]); 
uf.set_submit( 
"bt", 
function(form){ 
alert("表单已经提交了"); 
} 
); 
} 
); 
</script> 
<style> 
.suc { background-color:#00ff00;} 
.error { background-color:#ff0000;} 
</style> 
</head> 
<body> 
<input type="text" id="f1" name="f1"/><span id="t1"></span><br/> 
<input type="button" id="bt" value="提交"/> 
</body> 
</html>

要注意的地方就是在循环中使用闭包会茶几,必须用一个方法来代理一下,呵呵

希望对初学js但是还不知道该做点什么怎么做的朋友能有所帮助

Javascript 相关文章推荐
让ie6也支持websocket采用flash封装实现
Feb 18 Javascript
AngularJS 服务详细讲解及示例代码
Aug 17 Javascript
使用json来定义函数,在里面可以定义多个函数的实现方法
Oct 28 Javascript
js简单正则验证汉字英文及下划线的方法
Nov 28 Javascript
canvas学习之API整理笔记(一)
Dec 29 Javascript
javascript 组合按键事件监听实现代码
Feb 21 Javascript
jQuery插件HighCharts绘制简单2D柱状图效果示例【附demo源码】
Mar 21 jQuery
JavaScript之json_动力节点Java学院整理
Jun 29 Javascript
javaScript产生随机数的用法小结
Apr 21 Javascript
vue中使用element ui的弹窗与echarts之间的问题详解
Oct 25 Javascript
js实现鼠标滑动到某个div禁止滚动
Sep 17 Javascript
vue里使用create, mounted调用方法
Apr 26 Vue.js
(jQuery,mootools,dojo)使用适合自己的编程别名命名
Sep 14 #Javascript
修改jquery里的dialog对话框插件为框架页(iframe) 的方法
Sep 14 #Javascript
基于jquery的划词搜索实现(备忘)
Sep 14 #Javascript
基于jquery的页面划词搜索JS
Sep 14 #Javascript
基于Jquery的实现回车键Enter切换焦点
Sep 14 #Javascript
js输出列表实现代码
Sep 12 #Javascript
JavaScript日历实现代码
Sep 12 #Javascript
You might like
C/S和B/S两种架构区别与优缺点分析
2014/10/23 PHP
PHPMailer使用QQ邮箱实现邮件发送功能
2017/08/18 PHP
TP3.2框架分页相关实现方法分析
2020/06/03 PHP
JS实现可调整倒计时间代码分享
2015/08/18 Javascript
基于JavaScript实现移除(删除)数组中指定元素
2016/01/04 Javascript
AngularJS 过滤器(自带和自建)详解
2016/09/19 Javascript
vue-cli+webpack在生成的项目中使用bootstrap实例代码
2017/05/26 Javascript
Angularjs 事件指令详细整理
2017/07/27 Javascript
基于canvas粒子系统的构建详解
2017/08/31 Javascript
Vue如何实现响应式系统
2018/07/11 Javascript
vue搜索和vue模糊搜索代码实例
2019/05/07 Javascript
微信js-sdk 录音功能的示例代码
2019/11/01 Javascript
vscode中的vue项目报错Property ‘xxx‘ does not exist on type ‘CombinedVueInstance<{ readyOnly...Vetur(2339)
2020/09/11 Javascript
[01:51]历届DOTA2国际邀请赛举办地回顾 TI9落地上海
2018/08/26 DOTA
[01:05:07]DOTA2-DPC中国联赛 正赛 DLG vs Dragon BO3 第一场2月1日
2021/03/11 DOTA
python实现通过pil模块对图片格式进行转换的方法
2015/03/24 Python
解决Python 中英文混输格式对齐的问题
2018/07/16 Python
python标准库sys和OS的函数使用方法与实例详解
2020/02/12 Python
Python的历史与优缺点整理
2020/05/26 Python
Python基于xlutils修改表格内容过程解析
2020/07/28 Python
详解如何使用Pytest进行自动化测试
2021/01/14 Python
惠普香港官方商店:HP香港
2019/04/30 全球购物
中专自我鉴定范文
2013/10/16 职场文书
大学生简短的自我评价分享
2014/02/20 职场文书
技术总监管理岗位职责
2014/03/09 职场文书
yy司仪主持词
2014/03/22 职场文书
创建绿色社区汇报材料
2014/08/22 职场文书
2014年小学班主任工作总结
2014/11/08 职场文书
小学优秀教师先进事迹材料
2014/12/16 职场文书
优秀团员事迹材料
2014/12/25 职场文书
食品药品安全责任书
2015/05/11 职场文书
民事调解书范文
2015/05/20 职场文书
中学音乐课教学反思
2016/02/18 职场文书
OpenCV绘制圆端矩形的示例代码
2021/08/30 Python
为什么MySQL 删除表数据 磁盘空间还一直被占用
2021/10/16 MySQL
基于PostgreSQL/openGauss 的分布式数据库解决方案
2021/12/06 PostgreSQL