在表单程序中,在页面上需要很多的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="/UploadFiles/2021-04-02/jquery-1.4.2.min.js"><script type="text/javascript" src="/UploadFiles/2021-04-02/kernel.js"><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但是还不知道该做点什么怎么做的朋友能有所帮助
华山资源网 Design By www.eoogi.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
华山资源网 Design By www.eoogi.com

《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线

暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。

艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。

《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。