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

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

面向?qū)ο蟮腏avascript之二(接口實現(xiàn)介紹)
接口是面向?qū)ο驤avascript工具箱中最有用的特性之一。我們都知道GOF在設(shè)計模式中說到:面向接口編程,而非面向?qū)崿F(xiàn)編程
2012-01-01 
js面向?qū)ο笤O(shè)計用{}好還是function(){}好(構(gòu)造函數(shù))
js面向?qū)ο笤O(shè)計用{}好還是function(){}好,大家給予了回復(fù),感覺不錯,特分享給大家。
2011-10-10 
JavaScript 構(gòu)造函數(shù) 面相對象學(xué)習(xí)必備知識
關(guān)于JavaScript構(gòu)造函數(shù),如今出現(xiàn)了很多JavaScript的框架,例如jQuery、Ext等等這些,這些將JavaScript作為一種面向?qū)ο蟮恼Z言進(jìn)行編程,那么JavaScript到底是怎么樣實現(xiàn)面向?qū)ο蟮囊恍┨卣鞯哪?,首先,我們來看看JavaScript怎么樣來定義一個構(gòu)造函數(shù)。
2010-06-06