手把手教你自己写一个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 相关文章推荐
jquery struts 验证唯一标识(公用方法)
Mar 27 Javascript
页面载入结束自动调用js函数示例
Sep 23 Javascript
js数值和和字符串进行转换时可以对不同进制进行操作
Mar 05 Javascript
jquery实现两个图片渐变切换效果的方法
Jun 25 Javascript
JavaScript实现节点的删除与序号重建实例
Aug 05 Javascript
bootstrap读书笔记之CSS组件(上)
Oct 17 Javascript
值得学习的bootstrap fileinput文件上传工具
Nov 08 Javascript
Angular 4依赖注入学习教程之Injectable装饰器(六)
Jun 04 Javascript
JS点击图片弹出文件选择框并覆盖原图功能的实现代码
Aug 25 Javascript
vue2.0实现移动端的输入框实时检索更新列表功能
May 08 Javascript
详解vue页面首次加载缓慢原因及解决方案
Nov 06 Javascript
javascript实现弹出层效果
Dec 10 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
PHP在字符串中查找指定字符串并删除的代码
2008/10/02 PHP
一贴学会PHP 新手入门教程
2009/08/03 PHP
php编程实现获取excel文档内容的代码实例
2011/06/28 PHP
浅谈PHP值mysql操作类
2016/06/29 PHP
php 基础函数
2017/02/10 PHP
laravel 中如何使用ajax和vue总结
2017/08/16 PHP
基于ThinkPHP5.0实现图片上传插件
2017/09/25 PHP
PHP 模拟登陆功能实例详解
2019/09/10 PHP
Jquery.LazyLoad.js修正版下载,实现图片延迟加载插件
2011/03/12 Javascript
Angular Js文件上传之form-data
2015/08/28 Javascript
详解nodejs 文本操作模块-fs模块(五)
2016/12/23 NodeJs
jquery easyui DataGrid简单示例
2017/01/23 Javascript
js实现百度登录框鼠标拖拽效果
2017/03/07 Javascript
JavaScript 函数的定义-调用、注意事项
2017/04/16 Javascript
原生JS+Canvas实现五子棋游戏
2020/05/28 Javascript
详解mpvue小程序中怎么引入iconfont字体图标
2018/10/01 Javascript
[04:15]DOTA2-DPC中国联赛 正赛 Ehome vs Aster 选手采访
2021/03/11 DOTA
Python针对给定列表中元素进行翻转操作的方法分析
2018/04/27 Python
python实现逐个读取txt字符并修改
2018/12/24 Python
Python中使用pypdf2合并、分割、加密pdf文件的代码详解
2019/05/21 Python
python 实现将文件或文件夹用相对路径打包为 tar.gz 文件的方法
2019/06/10 Python
关于Python-faker的函数效果一览
2019/11/28 Python
numpy.ndarray 实现对特定行或列取值
2019/12/05 Python
numpy按列连接两个维数不同的数组方式
2019/12/06 Python
解决Pytorch训练过程中loss不下降的问题
2020/01/02 Python
拿来就用!Python批量合并PDF的示例代码
2020/08/10 Python
美国沙龙美发产品购物网站:Hair.com by L’Oreal
2020/11/09 全球购物
聚网科技C++面试笔试题
2015/09/01 面试题
请编程遍历页面上所有 TextBox 控件并给它赋值为 string.Empty
2015/12/03 面试题
学生自我评语大全
2014/04/18 职场文书
办理房产过户的委托书
2014/09/14 职场文书
见习报告的格式
2014/11/04 职场文书
2014年党总支工作总结
2014/12/18 职场文书
教师求职简历自我评价
2015/03/10 职场文书
开会通知短信大全
2015/04/20 职场文书
生活委员竞选稿
2015/11/21 职场文书