基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解


Posted in Javascript onJuly 18, 2016

表单校验是页面开发中非常常见的一类需求,相信每个前端开发人员都有这方面的经验。网上有很多成熟的表单校验框架,虽然按照它们默认的设计,用起来没有多大的问题,但是在实际工作中,表单校验有可能有比较复杂的个性化的需求,使得我们用这些插件的默认机制并不能完成这些功能,所以要根据自己的需要去改造它们(毕竟自己还不到那个写一个完美的校验框架的层次)。我用过formValidation这个校验框架,虽然它跟bootstrap配合地很好,但是校验风格太死板,不太满足个性化的场景;后来我找到了jquery.validate,我发现这个框架还挺好的,因为它只提供校验机制,但是不提供特定校验的交互,有比较多的自定义的空间。在校验风格方面,有很多的形式,可以通过颜色,边框,动画,文本显示,弹框等多种方式来产生交互,至于要用哪种,就由需求以及自己的喜好来决定了。我偏向使用气泡提示的校验风格,因为气泡信息在界面上只显示于字段的周边,而不会对表单的内容有所改变,看起来体验比较好。本文介绍自己使用jquery.validate以及bootstrap的tooltip打造一种气泡式表单校验的思路,如果你有一些个性化较强的表单校验需求,希望这篇文章能对你有些参考价值。

在线demo(点击下面链接页面中的保存按钮,或者改变表单元素的值都能触发校验):

http://liuyunzhuge.github.io/blog/form/dist/html/demo3.html

demo相关的逻辑代码:

https://github.com/liuyunzhuge/blog/blob/master/form/src/js/app/demo3.js

效果预览:

基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解

组件实现:

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对象。

通过前面对这两个方法的描述,大概就能知道该如何去完成自定义的表单校验功能了:

1)如果在errorPlacement这个option里什么都不做,那么校验的时候就不会插入到页面中了;

2)在showErrors里面,通过errorList和successList,我们可以分别遍历一遍,给失败的元素显示tooltip,然后给成功的元素移除tooltip。

下图是简单说明我的实现中对jquery.validate调用时的方式,只用到了前面提到的这两个选项。

基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解

接下来就来看看实际实现时的一些要点。

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,//多久自动隐藏tooltip
fieldConfig: {},//按字段名称配置一些东西,如:
/**
 * {
 * 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>
 */

详细作用如下:

useTooltip决定了是否启用气泡校验的功能,默认为true,如果为false,validate.js提供的模块将使用默认的校验机制来显示校验逻辑;

tipPlacement: 全局的气泡提示显示的位置,用过bootstrap的tooltip就知道,它可以显示到一个元素的上下左右,通过这个可以改变气泡提示的默认位置;

tooltipDuration: 配置气泡显示的时间。我提供的实现,在显示气泡时的逻辑是:在校验失败的时候,显示tootip,然后在这个选项指定的时间过去之后,自动消失,当鼠标再次移入失败元素的时候,tooltip会再次显示,鼠标移出的时候再消失。

fieldConfig:可以用来根据字段名称做一些配置,注释中有配举例。可配置的选项说明如下:

- fvTipTarget:用来自定义气泡显示在哪个元素上; - tipPlacement:配置某个元素气泡提示的显示位置 - tooltipClass:自定义气泡组件的css类 - errorPlacement:自定义某个元素的失败信息的插入位置 - fvRelatedTarget:自定义元素校验时需要关联影响的其它元素,其实就是在表单元素校验失败的时候也把相关的validClass和errorClass这两个css类,同步管理到其它元素而已。

需要注意的是,fieldConfig是根据字段元素名称来配置的,因为只能根据名称来找到相应的元素,所以表单元素上面一定要有name属性,这样才能找到fieldConfig中的配置项。

fieldTypeConfig:可以用来按字段类型做一些配置,它的配置项跟fieldConfig的一致,只不过它的好处在于,可以为同一个类型的字段指定相同的配置,省的在fieldConfig里面要重复配置。

需要注意的是:fieldType是通过在表单元素上的type属性或者data-type属性或者data-fv-type属性来指定的,优先级:data-fv-type > data-type > type。在fieldTypeConfig中,可以使用all这个特殊的type,它不需要在表单元素上指定,用来对所有的字段进行一个统一的配置。在validate.js模块的静态成员上,提供了defaultFieldTypeConfig对象,通过扩展这个对象,可以提供默认的一些按字段类型的配置,方便做一些统一处理。最后一点在静态成员部分还会再详细介绍。

jquery.validate相关的一些需要覆盖的option及其说明如下:

debug: true,//防止校验成功后表单自动提交
submitHandler: $.noop,//屏蔽表单校验成功后的表单提交功能,由外部的Form组件负责提交
ignore: '[type="hidden"]:not(.fv-yes),[disabled]:not(.fv-yes),.fv-no',//用于过滤不参与校验的元素
errorElement: 'i',//使用<i>元素来包裹校验失败的信息
errorClass: 'fv-error',//校验失败时相应的class
validClass: 'fv-valid'//校验成功时相应的class

需要补充的是:

a. 为啥要防止表单自动提交,因为我自己更偏向于主动控制表单提交;

b. ignore部分,没有完全把隐藏的或者禁用的表单元素排除掉,有一些时候隐藏元素也是能够用于校验的。

3)核心实现

核心实现的方法就是下面的代码:

$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();
 }
}));

这两个代码应该很好理解,因为各个部分的逻辑都已经单独抽出来封装了,细节可以逐一去阅读了解:

基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解

以上每个方法都比较简单,所以就不拆开来介绍了。

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)表单校验重置

一个很普遍的需求,就是有的时候需要重置表单,这个时候除了重置表单元素的值,还得重置它们的校验状态,虽然jquery.validate有提供相关方法,但是由于我们有用到tooltip组件以及添加了一些其它处理,所以需要对表单校验的重置功能,做一些自定义,主要是tooltip组件的销毁和一些状态的还原:

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)静态成员

validate.js提供了一些静态成员,有属性也有方法,使用的方法见mod/formValidation.js。其中

defaultFieldTypeConfig:用来存储全局的一些按字段类型的配置项;

extendFieldTypeConfig:用来扩展defaultFieldTypeConfig。

validateEvents:用来存储全局的一些自定义的校验事件。

addValidateEvent和removeValidateEvent用来添加和移除自定义的校验事件。

为什么会有自定义的校验事件?因为在jquery.validate这个插件的默认机制下,有些表单元素的change事件并不会触发当前元素的校验,导致界面上不能实时反馈元素的校验状态。这个用来帮助我们自动的注册一些元素的特殊事件,然后在这些事件回调内主动触发对元素的校验。

3. 使用举例

从demo相关的逻辑代码中,就看到实际的使用举例:

基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解

基于jQuery.validate及Bootstrap的tooltip开发气泡样式的表单校验组件思路详解

从这个举例也能看到,新的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这种已有的校验框架来完成个性化的表单校验功能思路,将来在碰到其它的个性化校验需求的时候,也完全可参照这个思路,尝试去做些统一的自定义组件,毕竟基于已有的成果去扩展比自己去造轮子,要来的更快更轻一些。本文提供的校验方式,使用起来还是挺爽的,也支持校验规则的增删改,方式同官方文档,欢迎使用并讨论相关的问题,我在项目中都用它,尤其在管理系统里面开发的时候,非常高效。

以上所述希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jquery统计输入文字的个数并对其进行判断
Jan 07 Javascript
JavaScript中的无阻塞加载性能优化方案
Oct 10 Javascript
JavaScript汉诺塔问题解决方法
Apr 21 Javascript
浅谈JavaScript中指针和地址
Jul 26 Javascript
浅谈JavaScript 中有关时间对象的方法
Aug 15 Javascript
纯js模仿windows系统日历
Feb 04 Javascript
JavaScript中利用构造器函数模拟类的方法
Feb 16 Javascript
jQuery设计思想
Mar 07 Javascript
angular.extend方法的具体使用
Sep 14 Javascript
vue 左滑删除功能的示例代码
Jan 28 Javascript
VSCode插件安装完成后的配置(常用配置)
Aug 24 Javascript
解决ant-design-vue中menu菜单无法默认展开的问题
Oct 31 Javascript
javascript时间差插件分享
Jul 18 #Javascript
如何用js实现鼠标向上滚动时浮动导航
Jul 18 #Javascript
终于实现了!精彩的jquery弹幕效果
Jul 18 #Javascript
全面解析JavaScript中“&amp;&amp;”和“||”操作符(总结篇)
Jul 18 #Javascript
全面介绍javascript实用技巧及单竖杠
Jul 18 #Javascript
Bootstrap 布局组件(全)
Jul 18 #Javascript
js验证真实姓名与身份证号,手机号的简单实例
Jul 18 #Javascript
You might like
PHP计算2点经纬度之间的距离代码
2013/08/12 PHP
ThinkPHP中自定义错误页面和提示页面实例
2014/11/22 PHP
制作个性化的WordPress登陆界面的实例教程
2016/05/21 PHP
PHP实现字母数字混合验证码功能
2019/07/11 PHP
js和jquery设置disabled属性为true使按钮失效
2014/08/07 Javascript
JsRender for index循环索引用法详解
2014/10/31 Javascript
flexslider.js实现移动端轮播
2017/02/05 Javascript
Bootstrap modal 多弹窗之叠加关闭阴影遮罩问题的解决方法
2017/02/27 Javascript
使用jQuery监听扫码枪输入并禁止手动输入的实现方法(推荐)
2017/03/21 jQuery
JavaScript实现的搜索及高亮显示功能示例
2017/08/14 Javascript
vue服务端渲染的实例代码
2017/08/28 Javascript
vue-lazyload图片延迟加载插件的实例讲解
2018/02/09 Javascript
JSON基本语法及与JavaScript的异同实例分析
2019/01/04 Javascript
JavaScript使用闭包模仿块级作用域操作示例
2019/01/21 Javascript
详解Vue+elementUI build打包部署后字体图标丢失问题
2020/07/13 Javascript
js实现抽奖功能
2020/11/24 Javascript
Python深入学习之闭包
2014/08/31 Python
python 截取 取出一部分的字符串方法
2017/03/01 Python
python中利用Future对象回调别的函数示例代码
2017/09/07 Python
使用Eclipse如何开发python脚本
2018/04/11 Python
对Python正则匹配IP、Url、Mail的方法详解
2018/12/25 Python
python3调用windows dos命令的例子
2019/08/14 Python
Python调用钉钉自定义机器人的实现
2020/01/03 Python
Python sys模块常用方法解析
2020/02/20 Python
python Yaml、Json、Dict之间的转化
2020/10/19 Python
css3动画效果抖动解决方法
2018/09/03 HTML / CSS
Rag & Bone官网:瑞格布恩高级成衣
2018/04/19 全球购物
介绍一下Linux中的链接
2016/06/05 面试题
会计应届生的自荐信
2013/12/13 职场文书
旅游与环境专业求职信
2014/06/05 职场文书
学校安全防火方案
2014/06/07 职场文书
六查六看自检自查剖析材料
2014/10/14 职场文书
委托书英文
2015/01/28 职场文书
广告策划的实习心得体会总结!
2019/07/22 职场文书
基于JavaScript实现省市联动效果
2021/06/22 Javascript
MySQL系列之十 MySQL事务隔离实现并发控制
2021/07/02 MySQL