手把手教你自己写一个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 实现窗口的最大化不论什么情况
Sep 03 Javascript
js实现点击左右按钮轮播图片效果实例
Jan 29 Javascript
js实现鼠标滚轮控制图片缩放效果的方法
Feb 20 Javascript
js实现仿网易点击弹出提示同时背景变暗效果
Aug 13 Javascript
jQuery实现的分子运动小球碰撞效果
Jan 27 Javascript
深入浅析Extjs中store分组功能的使用方法
Apr 20 Javascript
JS 调试中常见的报错问题解决方法
May 20 Javascript
微信小程序支付之c#后台实现方法
Oct 19 Javascript
原生JS实现瀑布流插件
Feb 06 Javascript
基于express中路由规则及获取请求参数的方法
Mar 12 Javascript
js实现简单模态框实例
Nov 16 Javascript
Javascript如何递归遍历本地文件夹
Aug 06 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
帅气的琦玉老师
2020/03/02 日漫
PHP 用数组降低程序的时间复杂度
2009/12/04 PHP
从康盛产品(discuz)提取出来的模板类
2011/06/28 PHP
php遍历数组的4种方法总结
2014/07/05 PHP
从零开始学YII2框架(一)通过Composer安装Yii2框架
2014/08/20 PHP
PHP Mysqli 常用代码集合
2016/11/12 PHP
用roll.js实现的图片自动滚动+鼠标触动的特效
2007/03/18 Javascript
20个非常有用的PHP类库 加速php开发
2010/01/15 Javascript
JavaScript Event学习第四章 传统的事件注册模型
2010/02/07 Javascript
Jquery Ajax请求代码(2)
2011/01/07 Javascript
一个简单的Ext.XTemplate的实例代码
2012/03/18 Javascript
js中对象的声明方式以及数组的一些用法示例
2013/12/11 Javascript
js 判断图片是否加载完以及实现图片的预下载
2014/08/14 Javascript
jQuery选择器querySelector的使用指南
2015/01/23 Javascript
一张Web前端的思维导图分享
2015/07/03 Javascript
浅谈javascript获取元素transform参数
2015/07/24 Javascript
基于jquery实现一个滚动的分步注册向导-附源码
2015/08/26 Javascript
angular+ionic 的app上拉加载更新数据实现方法
2017/01/16 Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
2020/04/01 jQuery
微信小程序实现登录注册功能
2020/12/29 Javascript
matplotlib中legend位置调整解析
2017/12/19 Python
图解python全局变量与局部变量相关知识
2019/11/02 Python
Python基于pygame实现单机版五子棋对战
2019/12/26 Python
JetBrains PyCharm(Community版本)的下载、安装和初步使用图文教程详解
2020/03/19 Python
python 用opencv实现霍夫线变换
2020/11/27 Python
java字符串格式化输出实例讲解
2021/01/06 Python
纯HTML+CSS3制作导航菜单(附源码)
2013/04/24 HTML / CSS
正宗的日本零食和糖果订阅盒:Bokksu
2019/11/21 全球购物
新领导上任欢迎词
2014/01/13 职场文书
运动会通讯稿400字
2014/01/28 职场文书
社团招新策划书
2014/02/04 职场文书
公司总经理工作职责管理办法
2014/02/28 职场文书
未婚证明书模板
2014/10/08 职场文书
惊涛骇浪观后感
2015/06/05 职场文书
MySql开发之自动同步表结构
2021/05/28 MySQL
Python re.sub 反向引用的实现
2021/07/07 Python