手把手教你自己寫一個(gè)js表單驗(yàn)證框架的方法
更新時(shí)間:2010年09月14日 02:25:13 作者:
其實(shí)我自己也就能簡(jiǎn)單用用js而已,但是呢,相對(duì)很多初學(xué)者來說多懂了點(diǎn)Know How所以斗膽孟浪一下,將一些所得記錄下來,以供更多的初學(xué)者能夠知道一個(gè)東西的實(shí)現(xiàn)過程,省去在源碼里摸索的過程。
在表單程序中,在頁(yè)面上需要很多的Js代碼來驗(yàn)證表單,每一個(gè)field是否必須填寫,是否
只能是數(shù)字,是否需要ajax到遠(yuǎn)程驗(yàn)證,blablabla。
如果一個(gè)一個(gè)單獨(dú)寫勢(shì)必非常的繁瑣,所以我們的第一個(gè)目標(biāo)就是構(gòu)建一個(gè)類似DSL的東西,
用表述的語(yǔ)句而非控制語(yǔ)句來實(shí)現(xiàn)驗(yàn)證。
其次一個(gè)個(gè)單獨(dú)寫的話還有一個(gè)問題就是必須全部驗(yàn)證通過才能提交,但是單獨(dú)驗(yàn)證會(huì)因?yàn)?
這個(gè)特征而增加很多額外的控制代碼,且經(jīng)常會(huì)驗(yàn)證不全面。所以第二個(gè)目標(biāo)就是能夠全面
的整合整個(gè)驗(yàn)證的過程。
最后不能是一個(gè)無法擴(kuò)展的一切寫死的實(shí)現(xiàn),必要的擴(kuò)展性還是要的。
首先,我們需要一個(gè)能夠描述對(duì)字段驗(yàn)證的類
function Field(params){
this.field_id=params.fid; //要驗(yàn)證的字段的ID
this.validators=params.val; //驗(yàn)證器對(duì)象數(shù)組
this.on_suc=params.suc; //當(dāng)驗(yàn)證成功的時(shí)候執(zhí)行的事件
this.on_error=params.err; //當(dāng)驗(yàn)證失敗的時(shí)候執(zhí)行的事件
this.checked=false; //是否通過驗(yàn)證
}
關(guān)于驗(yàn)證器對(duì)象我們?cè)诤竺鎭碛懻摚酉聛砦覀償U(kuò)展這個(gè)類,加入validate方法
Field.prototype.validate=function(){
//循環(huán)每一個(gè)驗(yàn)證器
for(item in this.validators){
//給驗(yàn)證器附加驗(yàn)證成功和驗(yàn)證失敗的回調(diào)事件
this.set_callback(this.validators[item]);
//執(zhí)行驗(yàn)證器上的Validate方法,驗(yàn)證是否符合規(guī)則
if(!this.validators[item].validate(this.data())){
break; //一旦任意一個(gè)驗(yàn)證器失敗就停止
}
}
}
再加入一個(gè)獲取字段值的方法:
//獲取字段值的方法
Field.prototype.data=function(){
return document.getElementById(this.field_id).value;
}
設(shè)置驗(yàn)證器回調(diào)函數(shù)的方法set_callback如下:
Field.prototype.set_callback=function(val){
var self=this; //換一個(gè)名字來存儲(chǔ)this,不然函數(shù)的閉包中會(huì)覆蓋這個(gè)名字
val.on_suc=function(){ //驗(yàn)證成功執(zhí)行的方法
self.checked=true; //將字段設(shè)置為驗(yàn)證成功
self.on_suc(val.tips); //執(zhí)行驗(yàn)證成功的事件
}
val.on_error=function(){ //驗(yàn)證失敗的時(shí)候執(zhí)行的方法
self.checked=false; //字段設(shè)置為驗(yàn)證失敗
self.on_error(val.tips);//執(zhí)行驗(yàn)證失敗的事件
}
}
接下來我們就來看看驗(yàn)證器,驗(yàn)證器是真正執(zhí)行驗(yàn)證過程的類,根據(jù)一般的驗(yàn)證過程,我們
可以將其分類成,長(zhǎng)度驗(yàn)證(包括必填驗(yàn)證),正則表達(dá)式驗(yàn)證,自定義函數(shù)驗(yàn)證,Ajax遠(yuǎn)
程驗(yàn)證這幾種,所以我們定義這幾種驗(yàn)證器類,Ajax遠(yuǎn)程驗(yàn)證為了方便引用了jQuery,其他
部分也有用到:
//長(zhǎng)度驗(yàn)證的驗(yàn)證器類
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;
}
//正則表達(dá)式驗(yàn)證器
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;
}
}
//遠(yuǎn)程驗(yàn)證器
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;
}
//自定義函數(shù)驗(yàn)證器
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();
}
}
最后我們用一個(gè)userform的類來做一個(gè)入口,在構(gòu)造的時(shí)候傳入Field對(duì)象的列表,并且將
每一個(gè)控件的onblur事件綁定到validate的包裝器上
function UserForm(items){
this.f_item=items; //把字段驗(yàn)證對(duì)象數(shù)組復(fù)制給屬性
for(idx=0;idx<this.f_item.length;idx++){ //循環(huán)數(shù)組
var fc=this.get_check(this.f_item[idx]); //獲取封裝后的回調(diào)事件
$("#"+this.f_item[idx].field_id).blur(fc); //綁定到控件上
}
}
//綁定驗(yàn)證事件的處理器,為了避開循環(huán)對(duì)閉包的影響
UserForm.prototype.get_check=function(v){
return function(){ //返回包裝了調(diào)用validate方法的事件
v.validate();
}
}
接下來需要定義一個(gè)方法來綁定提交按鈕的onclick事件:
//綁定提交事件到元件
UserForm.prototype.set_submit=function(bid,bind){
var self=this;
$("#"+bid).click(
function(){
if(self.validate()){
bind();
}
}
);
}
這里提到了一個(gè)UserForm的validate方法,如下:
//驗(yàn)證所有的字段
UserForm.prototype.validate=function(){
for(idx in this.f_item){ //循環(huán)每一個(gè)驗(yàn)證器
this.f_item[idx].validate(); //再檢測(cè)一遍
if(!this.f_item[idx].checked){
return false; //如果錯(cuò)誤就返回失敗,阻止提交
}
}
return true; //一個(gè)都沒錯(cuò)就返回成功執(zhí)行提交
}
最后用一個(gè)例子來看看怎么用:
<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,"長(zhǎng)度錯(cuò)誤"),new Exp_val(v_int,"不是數(shù)字")],
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("表單已經(jīng)提交了");
}
);
}
);
</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>
要注意的地方就是在循環(huán)中使用閉包會(huì)茶幾,必須用一個(gè)方法來代理一下,呵呵
希望對(duì)初學(xué)js但是還不知道該做點(diǎn)什么怎么做的朋友能有所幫助
只能是數(shù)字,是否需要ajax到遠(yuǎn)程驗(yàn)證,blablabla。
如果一個(gè)一個(gè)單獨(dú)寫勢(shì)必非常的繁瑣,所以我們的第一個(gè)目標(biāo)就是構(gòu)建一個(gè)類似DSL的東西,
用表述的語(yǔ)句而非控制語(yǔ)句來實(shí)現(xiàn)驗(yàn)證。
其次一個(gè)個(gè)單獨(dú)寫的話還有一個(gè)問題就是必須全部驗(yàn)證通過才能提交,但是單獨(dú)驗(yàn)證會(huì)因?yàn)?
這個(gè)特征而增加很多額外的控制代碼,且經(jīng)常會(huì)驗(yàn)證不全面。所以第二個(gè)目標(biāo)就是能夠全面
的整合整個(gè)驗(yàn)證的過程。
最后不能是一個(gè)無法擴(kuò)展的一切寫死的實(shí)現(xiàn),必要的擴(kuò)展性還是要的。
首先,我們需要一個(gè)能夠描述對(duì)字段驗(yàn)證的類
復(fù)制代碼 代碼如下:
function Field(params){
this.field_id=params.fid; //要驗(yàn)證的字段的ID
this.validators=params.val; //驗(yàn)證器對(duì)象數(shù)組
this.on_suc=params.suc; //當(dāng)驗(yàn)證成功的時(shí)候執(zhí)行的事件
this.on_error=params.err; //當(dāng)驗(yàn)證失敗的時(shí)候執(zhí)行的事件
this.checked=false; //是否通過驗(yàn)證
}
關(guān)于驗(yàn)證器對(duì)象我們?cè)诤竺鎭碛懻摚酉聛砦覀償U(kuò)展這個(gè)類,加入validate方法
復(fù)制代碼 代碼如下:
Field.prototype.validate=function(){
//循環(huán)每一個(gè)驗(yàn)證器
for(item in this.validators){
//給驗(yàn)證器附加驗(yàn)證成功和驗(yàn)證失敗的回調(diào)事件
this.set_callback(this.validators[item]);
//執(zhí)行驗(yàn)證器上的Validate方法,驗(yàn)證是否符合規(guī)則
if(!this.validators[item].validate(this.data())){
break; //一旦任意一個(gè)驗(yàn)證器失敗就停止
}
}
}
再加入一個(gè)獲取字段值的方法:
復(fù)制代碼 代碼如下:
//獲取字段值的方法
Field.prototype.data=function(){
return document.getElementById(this.field_id).value;
}
設(shè)置驗(yàn)證器回調(diào)函數(shù)的方法set_callback如下:
復(fù)制代碼 代碼如下:
Field.prototype.set_callback=function(val){
var self=this; //換一個(gè)名字來存儲(chǔ)this,不然函數(shù)的閉包中會(huì)覆蓋這個(gè)名字
val.on_suc=function(){ //驗(yàn)證成功執(zhí)行的方法
self.checked=true; //將字段設(shè)置為驗(yàn)證成功
self.on_suc(val.tips); //執(zhí)行驗(yàn)證成功的事件
}
val.on_error=function(){ //驗(yàn)證失敗的時(shí)候執(zhí)行的方法
self.checked=false; //字段設(shè)置為驗(yàn)證失敗
self.on_error(val.tips);//執(zhí)行驗(yàn)證失敗的事件
}
}
接下來我們就來看看驗(yàn)證器,驗(yàn)證器是真正執(zhí)行驗(yàn)證過程的類,根據(jù)一般的驗(yàn)證過程,我們
可以將其分類成,長(zhǎng)度驗(yàn)證(包括必填驗(yàn)證),正則表達(dá)式驗(yàn)證,自定義函數(shù)驗(yàn)證,Ajax遠(yuǎn)
程驗(yàn)證這幾種,所以我們定義這幾種驗(yàn)證器類,Ajax遠(yuǎn)程驗(yàn)證為了方便引用了jQuery,其他
部分也有用到:
復(fù)制代碼 代碼如下:
//長(zhǎng)度驗(yàn)證的驗(yàn)證器類
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;
}
//正則表達(dá)式驗(yàn)證器
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;
}
}
//遠(yuǎn)程驗(yàn)證器
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;
}
//自定義函數(shù)驗(yàn)證器
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();
}
}
最后我們用一個(gè)userform的類來做一個(gè)入口,在構(gòu)造的時(shí)候傳入Field對(duì)象的列表,并且將
每一個(gè)控件的onblur事件綁定到validate的包裝器上
復(fù)制代碼 代碼如下:
function UserForm(items){
this.f_item=items; //把字段驗(yàn)證對(duì)象數(shù)組復(fù)制給屬性
for(idx=0;idx<this.f_item.length;idx++){ //循環(huán)數(shù)組
var fc=this.get_check(this.f_item[idx]); //獲取封裝后的回調(diào)事件
$("#"+this.f_item[idx].field_id).blur(fc); //綁定到控件上
}
}
//綁定驗(yàn)證事件的處理器,為了避開循環(huán)對(duì)閉包的影響
UserForm.prototype.get_check=function(v){
return function(){ //返回包裝了調(diào)用validate方法的事件
v.validate();
}
}
接下來需要定義一個(gè)方法來綁定提交按鈕的onclick事件:
復(fù)制代碼 代碼如下:
//綁定提交事件到元件
UserForm.prototype.set_submit=function(bid,bind){
var self=this;
$("#"+bid).click(
function(){
if(self.validate()){
bind();
}
}
);
}
這里提到了一個(gè)UserForm的validate方法,如下:
復(fù)制代碼 代碼如下:
//驗(yàn)證所有的字段
UserForm.prototype.validate=function(){
for(idx in this.f_item){ //循環(huán)每一個(gè)驗(yàn)證器
this.f_item[idx].validate(); //再檢測(cè)一遍
if(!this.f_item[idx].checked){
return false; //如果錯(cuò)誤就返回失敗,阻止提交
}
}
return true; //一個(gè)都沒錯(cuò)就返回成功執(zhí)行提交
}
最后用一個(gè)例子來看看怎么用:
復(fù)制代碼 代碼如下:
<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,"長(zhǎng)度錯(cuò)誤"),new Exp_val(v_int,"不是數(shù)字")],
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("表單已經(jīng)提交了");
}
);
}
);
</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>
要注意的地方就是在循環(huán)中使用閉包會(huì)茶幾,必須用一個(gè)方法來代理一下,呵呵
希望對(duì)初學(xué)js但是還不知道該做點(diǎn)什么怎么做的朋友能有所幫助
您可能感興趣的文章:
- js驗(yàn)證框架之RealyEasy驗(yàn)證詳解
- js驗(yàn)證框架實(shí)現(xiàn)代碼分享
- 非常實(shí)用的js驗(yàn)證框架實(shí)現(xiàn)源碼 附原理方法
- 教你用AngularJS框架一行JS代碼實(shí)現(xiàn)控件驗(yàn)證效果
- AngularJS驗(yàn)證信息框架的封裝插件用法【w5cValidator擴(kuò)展插件】
- Node.js開發(fā)教程之基于OnceIO框架實(shí)現(xiàn)文件上傳和驗(yàn)證功能
- jquery validate.js表單驗(yàn)證的基本用法入門
- js驗(yàn)證表單大全
- JavaScript 表單驗(yàn)證正則表達(dá)式大全[推薦]
- 自定義javascript驗(yàn)證框架示例【附源碼下載】

javascript面向?qū)ο缶幊檀a,學(xué)習(xí)js面向?qū)ο缶幊痰呐笥芽梢詤⒖枷隆?/div> 2011-12-12

javascript面向?qū)ο缶幊?一) 實(shí)例代碼
javascript面向?qū)ο缶幊虒?shí)例代碼,代碼也算比較基礎(chǔ)了,不懂得朋友可以參考腳本之家之前發(fā)布的文章。
2010-06-06 
面向?qū)ο蟮腏avascript之二(接口實(shí)現(xiàn)介紹)
接口是面向?qū)ο驤avascript工具箱中最有用的特性之一。我們都知道GOF在設(shè)計(jì)模式中說到:面向接口編程,而非面向?qū)崿F(xiàn)編程
2012-01-01 
js面向?qū)ο笤O(shè)計(jì)用{}好還是function(){}好(構(gòu)造函數(shù))
js面向?qū)ο笤O(shè)計(jì)用{}好還是function(){}好,大家給予了回復(fù),感覺不錯(cuò),特分享給大家。
2011-10-10 
JavaScript 設(shè)計(jì)模式之組合模式解析
“組合模式”顧名思意就是將多種實(shí)現(xiàn)組合在一起而達(dá)到牽一處而動(dòng)全身的效果。
2010-04-04 
JavaScript 構(gòu)造函數(shù) 面相對(duì)象學(xué)習(xí)必備知識(shí)
關(guān)于JavaScript構(gòu)造函數(shù),如今出現(xiàn)了很多JavaScript的框架,例如jQuery、Ext等等這些,這些將JavaScript作為一種面向?qū)ο蟮恼Z(yǔ)言進(jìn)行編程,那么JavaScript到底是怎么樣實(shí)現(xiàn)面向?qū)ο蟮囊恍┨卣鞯哪?,首先,我們來看看JavaScript怎么樣來定義一個(gè)構(gòu)造函數(shù)。
2010-06-06