手把手教你自己写一个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 相关文章推荐
使用新的消息弹出框blackbirdjs
Oct 16 Javascript
基于jQuery的模仿新浪微博时间的组件
Oct 04 Javascript
基于jquery打造的百分比动态色彩条插件
Sep 19 Javascript
Javascript动态创建表格及删除行列的方法
May 15 Javascript
jQuery插件zTree实现的基本树与节点获取操作示例
Mar 08 Javascript
浅谈angularjs中响应回车事件
Apr 24 Javascript
详解react服务端渲染(同构)的方法
Sep 21 Javascript
ES6学习教程之模板字符串详解
Oct 09 Javascript
ES6知识点整理之函数数组参数的默认值及其解构应用示例
Apr 17 Javascript
vue 解决遍历对象显示的顺序不对问题
Nov 07 Javascript
Vue.js watch监视属性知识点总结
Nov 11 Javascript
vue 图片裁剪上传组件的实现
Nov 12 Javascript
(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
this和执行上下文实现代码
2010/07/01 Javascript
EasyUI中的tree用法介绍
2011/11/01 Javascript
jquery滚动条插件jScrollPane的使用介绍
2013/11/08 Javascript
Node.js实现的简易网页抓取功能示例
2014/12/05 Javascript
JavaScript如何动态创建table表格
2020/08/02 Javascript
jQuery实现简洁的轮播图效果实例
2016/09/07 Javascript
Bootstrap基本插件学习笔记之Popover提示框(19)
2016/12/08 Javascript
JavaScript 实现 Tab 点击切换实例代码
2017/03/25 Javascript
第一次记录Bootstrap table学习笔记(1)
2017/05/18 Javascript
JS中mouseup事件丢失的原因与解决办法
2017/06/14 Javascript
ionic环境配置及问题详解
2017/06/27 Javascript
Vue之Watcher源码解析(1)
2017/07/19 Javascript
基于Vuex无法观察到值变化的解决方法
2018/03/01 Javascript
vue弹窗组件的实现示例代码
2018/09/10 Javascript
angularJS实现不同视图同步刷新详解
2018/10/09 Javascript
详解解决小程序中webview页面多层history返回问题
2019/08/20 Javascript
Vue Extends 扩展选项用法完整实例
2019/09/17 Javascript
js实现点赞效果
2020/03/16 Javascript
vue iview实现动态新增和删除
2020/06/17 Javascript
深入分析在Python模块顶层运行的代码引起的一个Bug
2014/07/04 Python
Python实现的简单hangman游戏实例
2015/06/28 Python
flask框架中勾子函数的使用详解
2018/08/01 Python
Python数据结构与算法(几种排序)小结
2019/06/22 Python
python mqtt 客户端的实现代码实例
2019/09/25 Python
python 读取数据库并绘图的实例
2019/12/03 Python
python 实现多维数组(array)排序
2020/02/28 Python
Python grpc超时机制代码示例
2020/09/14 Python
阿拉伯世界最大的电子商务网站:Souq沙特阿拉伯
2016/10/28 全球购物
应届毕业生应聘自荐信
2013/12/07 职场文书
租房协议书
2014/04/10 职场文书
小学教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
山楂树之恋观后感
2015/06/11 职场文书
爱的教育读书笔记
2015/06/26 职场文书
创业计划书之健康营养产业
2019/10/15 职场文书
教你用Java在个人电脑上实现微信扫码支付
2021/06/13 Java/Android
聊聊CSS粘性定位sticky案例解析
2022/06/01 HTML / CSS