复制代码 jQuery.Validate为我们提供了3种验证编写方式,各有优缺点: 1、在input对象中书写class样式指定验证规则或属性验证规则: 如 最简单、最便捷,提示消息使用jQuery.Validate的内置的消息(自定义扩展验证规则也属于此项),但是由于是以样式名的方式进行验证,导致了日后修改必须找到相应的input对象,同时无法使用高级验证规则,具体说明请向下看 2、同第1条,这种验证规则方式也是在input对象中书写class样式,只不过书写的方式改为了JSON格式,但是这种方式提供了自定义验证消息的支持: 如 可以看到这样写验证规则虽然简单,但是如果我要为这个控件应用其他样式怎么办?所以现在就是处理这个问题的时候了,在页面的头部加上一句代码: jQuery.metadata.setType("attr", "validate"); 由于这种验证规则方式需要依赖jQuery.metadata才可以正常运作,所以我们需要在jQuery.metadata上做文章,分析下jQuery.metadata的代码,可以看到,默认情况下它是检测控件的class属性: defaults : { type: ‘class‘, name: ‘metadata‘, cre: /({.*})/, single: ‘metadata‘ } 那我们可不可以更改这个属性呢?肯定是可以的,就是在页面上加上那句代码,更改其检测的属性。 接着我们还需要修改下页面中的代码,将原来所有的"CssClass”改为我们更改的检测属性"validate”、 这样就很好的更改了验证规则所存放的属性了。 第2点:在ASP.NET下,所有的按钮都会提交form表单,所以都会引发验证,如何处理?(具体见Middle-4.aspx中btnNoValidate按钮) 在实际的开发当中,一个页面上总会有N个按钮,由于ASP.NET的机制特性,所有的控件都会回发页面,也就提交了表单,但是此时整个表单都被jQuery.Validate所监控,所以只要页面中有某个地方不符合验证规则,任何回发页面的操作都会被拦截住,但是实际上我们需要引发验证的按钮只有1或者2个,而其他按钮不需要,这时我们就要想办法了。 其实很简单,就是为不需要引发验证的控件加个样式"cancel"即可,代码如下: 怎么样很简单吧? 第3点:我希望验证的提示信息可以在统一的地方显示,如何处理?(具体见Middle-5.aspx) 在开发的过程当中,会有一些特殊的需求,就比如页面上使用了tab页面,而提交按钮就一个,这时就需要将验证提示信息统一放在一个位置,好方便查看,如图: pic21 要实现这个效果只需在JS编写验证规则时添加: errorPlacement: function(error, element) { error.html(error.html()+"
"); error.appendTo("#errorContainer"); } error是一个label对象里面包含了错误消息,element则是验证未通过的对象元素,通过errorPlacement可以方便的将验证提示信息统一放入一个位置。 第4点:我在开发的过程中,我不确定所编写的规则是否正确,如何进行调试?(具体见Middle-5.aspx) 这个就比较简单了,jQuery.Validate默认已经为我们考虑过了,只需在JS编写规则时添加一个属性: debug:true 这样就表示现在在调试,这时不会提交表单。 第5点:我使用的是微软AJAX控件,想监控dropdownlist是否选择,为何不起作用?(具体见Middle-5.aspx中的性别) 在使用微软AJAX控件中的dropdownlist级联时,比如省市区联动,如果省没有选择,则市和区都是灰的,是disabled状态,是被禁用的,类似代码如下: 男 女 我这边是强制把这个DropDownList禁用了,这时如果为这个控件加上“required”将不会有任何反应,因为在jQuery.Validate代码中默认是不验证的,具体代码见jQuery.Validate.js414行: not(":submit, :reset, :image, [disabled]") 所以为了方便我们使用,我们修改下代码,将[disabled]"去除,改为: not(":submit, :reset, :image") 这样再刷新下页面,验证就起作用了。 第6点:radiobox,checkbox,listbox如何进行高级应用?如何指定选择数量?(具体请见radio-checkbox-select-demo.html) 这点我直接引用了官方关于radiobox,checkbox,listbox应用的例子,因为官方的例子已经写的非常好了。 1、扩展验证规则,jQuery.Validate只提供了一些基本的验证功能,并不能满足我们日常开发的需求,所以我们要为jQuery.Validate扩展验证规则。 2、分组验证,在开发的时候有时会遇到的一个问题就是,不同按钮引发不同的验证。 首先来介绍下第一点:扩展验证规则,在jQuery.Validate默认的验证规则无法满足我们的日常开发需求的时候,我们需要根据自己的业务需求指定一些相应的规则。(具体见MasterPage.master) 为了扩展验证规则,我们首先要看下jQuery.Validate为我们提供的扩展方法: addMethod: function(name, method, message) { $.validator.methods[name] = method; $.validator.messages[name] = message; if (method.length < 3) { $.validator.addClassRules(name, $.validator.normalizeRule(name)); } }, 这段代码就是用来扩展验证规则的,意思很简单,就是向jQuery.Validate添加验证方法。 接收3个参数:name-验证规则名 method-验证规则实现函数(function) message-验证不通过显示的错误消息 当我们调用了这个方法后,我们所写的规则自动就会加入到jQuery.Validate规则中。 好了,我们看下具体如何实现: 手机号码验证: jQuery.validator.addMethod("telphoneValid", function(value, element) { var tel = /^(130|131|132|133|134|135|136|137|138|139|150|153|157|158|159|180|187|188|189)\d{8}$/; return tel.test(value) || this.optional(element); }, "请输入正确的手机号码"); 这边的method需要注意的是,这个method实现函数接收2个元素: value:检测的对象的值 element:检测的对象 这边我定义了一个名为“telphoneValid”的验证规则,在验证规则里我首先定义了个手机验证的正则表达式,然后将值放入正则表达式进行验证,返回验证结果,返回的错误消息是“请输入正确的手机号码”。 这样就完成了一个简单的手机号码验证规则扩展。 第2点:分组验证,这个分组验证在默认的jQuery.Validate中默认是不支持的,也是我觉得很不爽的,因为在实际的开发过程中经常会碰到需要分组验证的时候。 这点微软的验证控件就做的很好,在微软的控件里,默认都有ValidationGroup这个属性,只要把属性名设置为相同就可以进行分组验证了,但是jQuery.Validate自身却没提供这个功能,所以我们只能自己扩展了。 来一下具体的场景,在一个页面里有2个tab页面,不同tab页面需要不同的提交按钮: pic22 pic23 这2个就是标准的分组验证情况,如果不设置分组验证的情况下,点击[基本信息提交]和[描述提交]按钮后页面上所有的验证都会被相应,这是因为2个按钮都在一个form表单中,2个按钮的点击事件默认都是在客户端提交表单,然后由服务器端来分配执行代码,所以问题就出现了。 这时我们就需要引入分组验证了,这个解决思路是我在一个国外的网站找到的,不过具体地址我找不到了,这个方法有个弊端就是必须是将需要分组的控件必须放入不同的容器中,如div,table等,因为采用的是标识class样式来进行分组验证。 看下具体代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 //初始化分组验证 function InitValidationGroup() { $(‘.validationGroup .causesValidation‘).click(Validate); $(‘.validationGroup :text‘).keydown(function(evt) { if (evt.keyCode == 13) { var $nextInput = $(this).nextAll(‘:input:first‘); if ($nextInput.is(‘:submit‘)) { Validate(evt); } else { evt.preventDefault(); $nextInput.focus(); } } }); } function Validate(evt) { var $group = $(this).parents(‘.validationGroup‘); var isValid = true; $group.find(‘:input‘).each(function(i, item) { if (!$(item).valid()) isValid = false; }); if (!isValid) evt.preventDefault(); } 上面的代码就是用来进行分组验证的初始化的,这段代码会找寻页面中标有validationGroup样式的元素(分组的容器),然后在这个元素中找带causesValidation样式的元素(这个元素是引发验证的按钮), 上面代码实现分组验证的逻辑就是当带causesValidation样式的元素引发验证后会找寻这个元素的父级validationGroup元素,然后遍历validationGroup元素下的所有有验证规则的元素判断是否验证通过。 页面代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
用户名 | |
密码 | |
确认密码 | |
姓名 | |
年龄 | |
性别 | 男 女 |
邮箱 | |
<script type="text/javascript"> InitRules(); isValidationGroup = true;</script> 分析下代码为2个tab页面都加上validationGroup样式,引发验证的按钮加上causesValidation样式,同时还需要标记一个isValidationGroup = true; 表示页面需要进行分组验证,传递回母版页。 注意:这边的逻辑和手写JS验证规则是一个逻辑,在母版页建立一个isValidationGroup属性默认为false,只有当页面需要进行分组验证则设为true。 接下来看下母版页的的jQuery(document).ready()中的带代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 if (isValidationGroup) { if (opts != undefined || opts != null) { jQuery("#").validate(jQuery.extend(opts, { onsubmit: false })); } else { jQuery("#").validate({ onsubmit: false }); } InitValidationGroup(); } else { if (opts != undefined || opts != null) { jQuery("#").validate(opts); } else { jQuery("#").validate(); } } 判断isValidationGroup是否需要进行分组验证,同时如果isValidationGroup为true,需要加入onsubmit:false,否则分组验证将无法有效。 1、如何使用jQuery.Validate进行AJAX验证? 2、默认jQuery.Validate在进行AJAX验证时返回必须是bool类型,如何返回一个对象包括错误消息及验证结果? 3、在反复使用jQuery.Validate进行AJAX验证时,总是需要编写相关AJAX参数,可否进行进一步封装? 第一点:如何使用jQuery.Validate进行AJAX验证?(具体见High-2.aspx) jQuery.Validate为我们提供了一个方便的AJAX验证方式(封装了jQuery的AJAX,同时将jQuery的AJAX和jQuery.Validate的验证很好的结合在一起),在此我仅仅介绍jQuery.Validate在ASP.NET下如何进行AJAX验证,PHP、JSP等请查看官方例子。 我是采用jQuery.Validate+WebService进行AJAX验证,客户端编写jQuery.Validate的remote验证属性,服务器端采用WebSerice进行接收参数进行验证。 首先来看下jQuery.Validate的remote属性如何编写AJAX验证规则: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function InitRules() { opts = { rules: { : { required: true, remote:{ type: "POST", async: false, url: "WebService.asmx/CheckUid", dataType: "xml", data: {uid:function(){ return jQuery("#").val();}} } } } } } 如果使用过jQuery.ajax的朋友肯定会很熟悉这段代码,jQuery.Validate的remote采用和jQuery.ajax相同的参数设置(原因就上面所说的封装了jQuery.ajax的原因)。 这边来详细讲解下jQuery.Validate的remote的一些知识: 1、jQuery.Validate的remote默认可以直接填写远程验证的地址,格式为:remote:”validate.aspx”,但是很多情况下这个远程验证需要提交参数、返回类型等限制,所以就可以采用在“{}”中编写具体属性的方式来包装提交参数。 2、jQuery.Validate的remote官方代码中,远程的输出只能是true或者false,不允许有其他输出,这个我觉得不太好,具体的扩展在后面我会讲到。 3、jQuery.Validate的remote在使用时如果想提交参数需要以JSON的方式提交格式如下: 1 2 3 4 5 data: { uid:function(){ return jQuery("#").val(); } } 此处肯定会有人不明白,为什么参数需要以function的形式提交,而不是直接写 jQuery("#").val(); 这里我要说明的是:jQuery.Validate的验证规则是在页面加载的时候就已经被加载了的,如果还是像以往一样直接写"jQuery("#").val();",那么验证的时候提交给服务器端的数据永远是页面加载时txtUid控件的值。 而使用function的好处就是在页面加载的时候仅仅告诉jQuery.Validate,在控件需要进行remote验证的时候需要调用function这个函数,这样就保证了在执行remote验证的时候可以获取到最新的值 我还修改了jQuery.Validate的remote方法,先来看下我修改的代码(具体见scripts/jquery.validate1.js 896行): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 if (previous.old !== value) { previous.old = value; var validator = this; this.startRequest(element); var data = http://www.mamicode.com/{}; data[element.name] = value; $.ajax($.extend(true, { //url:url,//此URL无法获取 url: param.url,//获取param验证规则中所写路径 mode:"abort", port: "validate" + element.name, type: param.type, dataType: "json", //data:data, data: param.data || data,//获取param.data或data中所提交的参数 success: function(response) { 以下省略... } 这边我修改了url和data的获取方式,主要是因为在真正执行的时候,变量url是空的,所以需要从param中获取。 而data为什么要改成param.data || data,主要原因就是下面这句代码: data[element.name] = value; 这句代码的意思就是:为哪个控件设置远程验证就获取哪个控件的值,但是在实际的开发中,当遇到进行AJAX验证的时候会出现需要同时提交多个数据的情况,此时这句代码就是错误的了,所以需要改成 param.data || data,这样就能保证在提交多个数据的时候以多个数据为准。 下面来看下webservice的代码: [WebMethod] public bool CheckUid(string uid) { return uid == "testuid" ? true : false; } 相当的简单,就是判断下用户名是不是指定的用户名。 注意:webservice.cs中必须将[System.Web.Script.Services.ScriptService]这个特性取消注释,否则AJAX验证将无效! 第二点:默认jQuery.Validate在进行AJAX验证时返回必须是bool类型,如何返回一个对象包括错误消息及验证结果?(具体见App_Code/WebService.cs/CheckUid) 在第一点中介绍jQuery.Validate知识的时候就提到了,jQuery.Validate默认直接收true或false,但是在具体的开发中,我们会分层开发,三层或者多层,webservice在接收到验证请求后不做具体的处理直接调用逻辑层的验证方法,交由逻辑层进行验证操作(当然你也可以把验证全部写在webservice中,但是这样就体现不出分层的好处了),此时的验证会产生多种情况,以最常见的用户名验证为例: 1)用户名已存在,此时的消息应该是“用户名已存在,请重新输入!” 2)用户名不符合规则,此时的消息应该是“用户名不符合规则,请重新输入!” 3)验证时出现程序异常,此时的消息应该是“程序出现异常,请联系管理员!” 可以看出,仅仅一个用户名验证就会出现这3种信息,如果不返回一个明确的消息,仅仅告诉用户“用户名有误”,客户端的使用者将会相当的痛苦,因为使用者并不知道他的用户名输入到底错在哪了。 所以为了更好的客户体验,以及项目的合理性,我们在服务器端封装一个实体类(具体见AppCode/AjaxClass),代码如下: [Serializable] public class AjaxClass { public string Msg { get; set; } public int Result { get; set; } } 就是一个最简单的实体类,有2个属性,Msg和Result,Msg用于存放验证失败的信息,Result用于存放结果。 看下WebSerivce的代码如何修改: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 [WebMethod] public AjaxClass CheckUid(string uid) { //return uid == "testuid" ? true : false; AjaxClass ajaxClass = new AjaxClass(); try { if (uid == "testuid") { ajaxClass.Msg = "用户名已存在,请重新输入!"; ajaxClass.Result = 0; } else if (uid.IndexOf("test") == -1) { ajaxClass.Msg = "用户名格式不正确,用户名必须包含test,请重新输入!"; ajaxClass.Result = 0; } else { ajaxClass.Msg = "格式正确!"; ajaxClass.Result = 1; } } catch { ajaxClass.Msg = "程序出现异常,请联系管理员!"; ajaxClass.Result = 0; } return ajaxClass; } 上面的WebService就完整的实现了我先前说的3种错误情况(由于这边仅仅是例子所以就只有表示层,实际开发中需要分层开发,此代码应该放入业务逻辑层) 注意:在webservice返回值前,如果检查成功必须要为ajaxClass.Result = 1,否则客户端验证会无法通过。 虽然完成了服务器端的代码修改,但是直接运行页面还是会出错,这是因为我上面所说过的,jQuery.Validate的remote远程的输出只能是true或者false,我们来看下具体的代码,其中注释掉的就是原来官方的代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 success: function(response) { if (response.Result) {//if(response){ var submitted = validator.formSubmitted; validator.prepareElement(element); validator.formSubmitted = submitted; validator.successList.push(element); validator.showErrors(); } else { var errors = {}; //errors[element.name] = response.Result || validator.defaultMessage(element, "remote"); errors[element.name] = response.Msg; validator.showErrors(errors); } previous.message = response.Msg; //previous.valid = response; previous.valid = response.Result; validator.stopRequest(element, response.Result); } 可以看到一共修改了3处地方: 1、判断返回值,原来是直接判断response,现在则是判断response.Result,因为现在的response已经是一个包含消息及结果的对象了。 2、错误消息,原来的错误消息是直接获取默认配置好的消息,我这边是获取response.Msg。 3、设置previous对象,将previous对象的消息和结果设置为AJAX返回的消息和结果,以供jQuery.Validate下面代码的返回。 这样jQuery.Validate的remote的方法就修改了,但是并没有结束,原因是先前在AJAX提交参数的时候由于jQuery.Validate的验证规则的缘故,提交的参数并不是以JSON的格式提交的而是以{uid:function()}这样的方式,结果就导致了无法设置jQuery.AJAX的contentType:"application/json; charset=utf-8",如果设置了会出现以下错误: pic24这样从webservice返回的AjaxClass对象就无法像以往的JSON方式直接操作了,所以我们只能换一种格式——XML,因为webservice默认返回的数据是XML格式: <?xml version="1.0" encoding="utf-8" ?> -