组件实现:
https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/formValidation.js
https://github.com/liuyunzhuge/blog/tree/master/form/src/js/mod/validation
(有3个关联的文件,可通过以上链接查看)
其它事项:
1)本文提供的校验实现依赖jquery,jquery.validate,bootstrap,并采用seajs来做模块化管理;
2)本文的demo结合之前写的form组件来一起使用,form管理的相关文章有:
简洁易用的表单数据设置和收集管理组件
进一步丰富和简化表单管理的组件:form.js
相关文档:
1)jquery.validate使用说明 : https://jqueryvalidation.org/documentation/
2)tootip使用说明: http://v3.bootcss.com/javascript/#tooltips
下面就来看看该如何实现这个气泡式的表单校验吧。
1. 实现思路
用过jquery.validate就知道,这个插件默认的校验机制是在某一个表单元素校验失败后,把校验失败的信息用一个label元素包裹起来,然后插入到表单元素的后面。如果我们要换成气泡式的校验,那么首先就要考虑把它默认的插入失败信息的label元素的机制给取消掉,因为有了气泡,这个label显然是多余的;然后还要去修改它的校验控制逻辑,在元素校验失败的时候,用气泡组件显示失败信息,在校验成功的时候,移除可能存在的相关的气泡组件(因为这个元素之前如果有校验失败的情况,就会初始化相关的气泡组件)。至于这两个动作该怎么去处理,简单的方法就是改源码,但是改源码会带来更大的问题,一是不利于升级,二是不利于扩展,将来要做其它的个性化校验,就容易冲突。更好地办法是去查阅官方文档,找到最佳的api来做自定义,这样的话,就能完全避免改源码带来的问题。如果我们碰到改造一个已有的组件来完成另一个组件,并且不得不改源码的情况,更好的方式,不是直接把另一个组件的逻辑写到已有的组件里面,而是在已有的组件里面添加合适的接口,再通过接口来完成另一个组件。
翻阅jquery.validate的文档,可以了解到它最核心的api是validate这个方法,这是一个可以直接在jquery对象上调用的方法,在调用它的时候,可以通过option传递很多的选项,其中有两个选项,就可以用来完成我们的自定义功能:errorPlacement与showErrors,这两个方法的作用以及签名分别是:
errorPlacement : function(error, element) {…}用来自定义表单元素失败信息的插入位置,如果这个方法是一个空函数,那么失败信息就不会插入到DOM里面去。它有两个参数,error表示失败信息生成的jquery对象;element表示单个的表单元素的jquery对象。
showErrors: function(errorMap, errorList) {…}用来自定义校验信息的显示机制。它有两个参数,第一个参数以Object的形式,封装了当前校验操作的所有校验失败的信息;第二个参数errorList是一个数组,它的每个元素包含两个属性element和message分别代表失败的表单元素的jq对象和失败信息。另外在这个方法里面通过this.successList还可访问到所有校验成功的元素列表,这个successList也是一个数组,它的每个元素就是校验成功的表单元素的DOM对象。
接下来就来看看实际实现时的一些要点。
2. 详细实现
1)从代码组织说起
本文实现主要包含三个文件:
https://github.com/liuyunzhuge/blog/blob/master/form/src/js/mod/formValidation.js
https://github.com/liuyunzhuge/blog/tree/master/form/src/js/mod/validation(这个文件包含两个文件:validate.js和validator.js)
核心的文件是mod/validation文件夹下的两个。其中:
validate.js是最核心的代码,包含了所有的自定义逻辑; validator.js仅仅是对jquery.validate默认的校验信息做的重置,因为它默认是英文的,而我的项目环境不需要考虑英文,所以就在这个文件里做了统一的处理;另外如果要添加一些全局的校验器的话,也可以考虑添加在这里。
mod/formValidation.js是在页面中直接引用的文件,它依赖mod/validation/validate.js,同时基于validate.js提供的接口,注册了一些自定义的处理,这些自定义的处理我会在后面进行说明,它的作用仅仅是为了将validate.js的功能与我之前写的form相关组件结合起来使用。
如果你对本文的实现感兴趣,但是对我写的form相关组件不感兴趣的话,完全可以考虑只关注validate.js和validator.js,因为没有formValidation.js,它们的功能依然是完整的。
2)新添加的option
在validate.js中可以看到有一个DEFAULTS,来定义本文实现的组件模块的option,除了对jquery.validate插件相关的option进行覆盖,还增加了以下option,来完成更丰富的功能:
useTooltip: true,//配置是否启用气泡提示来显示校验失败的信息,默认启用tipPlacement: "right",//全局的气泡提示的位置tooltipDuration: 2500,//多久自动隐藏tooltipfieldConfig: {},//按字段名称配置一些东西,如:/** * { * title: { * fvTipTarget: function($field){ return $field.closest(...);}, //配置气泡提示关联的DOM元素 * tipPlacement: "top", //配置气泡提示的显示位置:上下左右 * tooltipClass: "tooltip-name", //配置气泡提示组件需要添加的css类 * errorPlacement: function(error,element){}, //配置字段错误信息的插入位置 * fvRelatedTarget: function($field){return ...}, //配置校验时关联影响的DOM元素 * } * } * * 其中fvTipTarget fvRelatedTarget可以是function和jQuery对象两种形式 */fieldTypeConfig: {},//按字段类型配置一些东西,如:/** * { * date: { * fvTipTarget: function($field){ return $field.closest(...);}, //配置date类型的字段校验失败时气泡提示关联的DOM元素 * tipPlacement: "top", //配置date类型的字段校验失败时气泡提示的显示位置:上下左右 * tooltipClass: "tooltip-name", //配置date类型的字段校验失败时气泡提示组件需要添加的css类 * errorPlacement: function(error,element){}, //配置date类型的字段的错误信息的插入位置 * fvRelatedTarget: function($field){return ...}, //配置date类型的字段时校验时关联影响的DOM元素 * } * } * 如果要为所有的类型定义一个配置,可把类型名称设置为all,如all: {errorPlacement: function(){..}} * 优先级: * fieldConfig > fieldTypeConfig<type> > Validation.defaultFieldTypeConfig > fieldTypeConfig<all> */详细作用如下:
debug: true,//防止校验成功后表单自动提交submitHandler: $.noop,//屏蔽表单校验成功后的表单提交功能,由外部的Form组件负责提交ignore: "[type="hidden"]:not(.fv-yes),[disabled]:not(.fv-yes),.fv-no",//用于过滤不参与校验的元素errorElement: "i",//使用<i>元素来包裹校验失败的信息errorClass: "fv-error",//校验失败时相应的classvalidClass: "fv-valid"//校验成功时相应的class需要补充的是:
$element.validate($.extend(opts, { errorPlacement: function (error, element) { if (opts.useTooltip) {return; } //jquery.validate组件默认的校验失败信息的插入方式是:在该元素后面插入校验失败的信息 //我们可以按字段及字段类型通过fieldConfig与fieldTypeConfig来自定义插入的方式 var _errorPlacement = getCommonConfig("errorPlacement", element, opts); if (!isFunc(_errorPlacement)) {_errorPlacement = function () {error.insertAfter(element);} } _errorPlacement(error, element); }, showErrors: function (errorMap, errorList) { //覆盖这个方法以便在校验失败的时候显示tooltip //不启用tooltip的时候按默认的方式显示失败信息 var successList = this.successList; //处理本次校验失败的字段 if ($.isArray(errorList)) {errorList.forEach(function (item) {setRelatedTargetStyle(item.element, opts, true);if (opts.useTooltip) { //显示失败的tooltip showErrorItem(item, opts, that);}}); } if ($.isArray(successList)) {successList.forEach(function (element) {setRelatedTargetStyle(element, opts, false);if (opts.useTooltip) { //移除原先可能失败导致的tooltip showSuccessItem(element, opts, that);}}); } //官方文档要求,在自定义showErrors之后,通过调用下面的方法完全内置的其它处理 this.defaultShowErrors(); }}));这两个代码应该很好理解,因为各个部分的逻辑都已经单独抽出来封装了,细节可以逐一去阅读了解:
以上每个方法都比较简单,所以就不拆开来介绍了。
4)继承jquery.validate提供的其它api方法
由于在实际的工作中,表单校验的逻辑有的时候会很复杂,尤其涉及到字段有增删改,校验规则有增删改的时候,所以去看jquery.valiate的文档,也能发现它提供了不止validate这个api,还有很多其它有用的方法,为了方便,所以直接把jquery.validate提供的其它validate.js不具备的方法都继承过来:
//将jquery.validate的api方法代理到自身for (var i in this._validator) { if (!(i in this) && isFunc(this._validator[i])) { this[i] = (function (context, func) {return function () {return func.apply(context, arguments);} })(this._validator, this._validator[i]); }}5)表单校验重置
resetForm: function () { var $element = this.$element, opts = this.options; //清除掉tooltip组件及绑定的事件 if (opts.useTooltip) { $element.find(".fv-tip-target").each(function () {var tooltip = $(this).data("bs.tooltip");checkHideTimeout(tooltip);tooltip && tooltip.destroy(); }).off(".fv"); } $element.find(".fv-related-target").removeClass(opts.validClass + " fv-related-target " + opts.errorClass); this._validator.resetForm();}6)静态成员
从这个举例也能看到,新的Validation组件跟直接使用jquery.validate没有太大的区别,就是多几个option,rules跟messages都是jquery.validate提供的option,而fieldTypeConfig是新提供的option;但是在功能上,校验的方式已经完全变成我所期待的的气泡式校验了,这个体验跟jquery.validate默认的体验比起来,肯定就要好很多了。
4. 相关CSS
为了正确显示demo中的校验效果,css也是很重要的一部分,demo相关的css可在src/css/form.css中去查找,跟校验相关的css可通过.fv这个关键词来搜索。
5. 总结
本文介绍了一种如何根据jquery.validate这种已有的校验框架来完成个性化的表单校验功能思路,将来在碰到其它的个性化校验需求的时候,也完全可参照这个思路,尝试去做些统一的自定义组件,毕竟基于已有的成果去扩展比自己去造轮子,要来的更快更轻一些。本文提供的校验方式,使用起来还是挺爽的,也支持校验规则的增删改,方式同官方文档,欢迎使用并讨论相关的问题,我在项目中都用它,尤其在管理系统里面开发的时候,非常高效。
以上所述希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!