手把手教你自己写一个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 相关文章推荐
JavaScript实现GriwView单列全选(自写代码)
May 13 Javascript
js对象的复制继承实例
Jan 10 Javascript
用jQuery向div中添加Html文本内容的简单实现
Jul 13 Javascript
原生javascript实现分页效果
Apr 21 Javascript
jquery.validate表单验证插件使用详解
Jun 21 jQuery
JS实现根据指定值删除数组中的元素操作示例
Aug 02 Javascript
详解如何理解vue的key属性
Apr 14 Javascript
js时间戳转yyyy-MM-dd HH-mm-ss工具类详解
Apr 30 Javascript
koa2+vue实现登陆及登录状态判断
Aug 15 Javascript
Vuex实现数据共享的方法
Dec 20 Javascript
vue点击按钮动态创建与删除组件功能
Dec 29 Javascript
Vue computed 计算属性代码实例
Apr 22 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.NET的入门教程
2006/10/09 PHP
PHP获取类中常量,属性,及方法列表的方法
2009/04/09 PHP
PHP 开发环境配置(Zend Server安装)
2010/04/28 PHP
thinkPHP中多维数组的遍历方法
2016/01/09 PHP
PHP实现数据分页显示的简单实例
2016/05/26 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
2019/11/21 PHP
PHP中类与对象功能、用法实例解读
2020/03/27 PHP
jQuery自定义事件的简单实现代码
2014/01/27 Javascript
用jQuery实现的智能隐藏、滑动效果的返回顶部代码
2014/03/18 Javascript
三种取消选中单选框radio的方法
2014/09/09 Javascript
JavaScript分页功能的实现方法
2015/04/25 Javascript
使用EVAL处理jqchart jquery 折线图返回数据无效的解决办法
2015/11/26 Javascript
浅谈jQuery为哪般去掉了浏览器检测
2016/08/29 Javascript
js中getter和setter用法实例分析
2018/08/14 Javascript
Angular6 用户自定义标签开发的实现方法
2019/01/08 Javascript
jquery中为什么能用$操作
2019/06/18 jQuery
JS中this的4种绑定规则详解
2020/02/04 Javascript
解决vue+elementui项目打包后样式变化问题
2020/08/03 Javascript
解决Vue-Router升级导致的Uncaught (in promise)问题
2020/08/07 Javascript
Python AES加密模块用法分析
2017/05/22 Python
python框架flask表单实现详解
2019/11/04 Python
python 已知三条边求三角形的角度案例
2020/04/12 Python
python实现npy格式文件转换为txt文件操作
2020/07/01 Python
Visual Studio Code搭建django项目的方法步骤
2020/09/17 Python
Python 实现图片转字符画的示例(静态图片,gif皆可)
2020/11/05 Python
CSS3盒子模型详解
2013/04/24 HTML / CSS
加拿大女包品牌:Matt & Nat
2017/05/12 全球购物
金牌葡萄酒俱乐部:Gold Medal Wine Club
2017/11/02 全球购物
师范生自荐信
2013/10/27 职场文书
高分子材料与工程专业推荐信
2013/12/01 职场文书
经营目标管理责任书
2014/07/25 职场文书
上班迟到检讨书范文300字
2014/11/02 职场文书
党支部先进事迹材料
2014/12/24 职场文书
2015年护士节活动总结
2015/02/10 职场文书
2015年三好一满意工作总结
2015/07/24 职场文书
Java8 Stream API 提供了一种高效且易于使用的处理数据的方式
2022/04/13 Java/Android