利用jquery.validate以及bootstrap的tooltip开发气泡式的表单校验组件
yuyutoo 2024-11-14 19:54 4 浏览 0 评论
表单校验是页面开发中非常常见的一类需求,相信每个前端开发人员都有这方面的经验。网上有很多成熟的表单校验框架,虽然按照它们默认的设计,用起来没有多大的问题,但是在实际工作中,表单校验有可能有比较复杂的个性化的需求,使得我们用这些插件的默认机制并不能完成这些功能,所以要根据自己的需要去改造它们(毕竟自己还不到那个写一个完美的校验框架的层次)。我用过formValidation这个校验框架,虽然它跟bootstrap配合地很好,但是校验风格太死板,不太满足个性化的场景;后来我找到了jquery.validate,我发现这个框架还挺好的,因为它只提供校验机制,但是不提供特定校验的交互,有比较多的自定义的空间。在校验风格方面,有很多的形式,可以通过颜色,边框,动画,文本显示,弹框等多种方式来产生交互,至于要用哪种,就由需求以及自己的喜好来决定了。我偏向使用气泡提示的校验风格,因为气泡信息在界面上只显示于字段的周边,而不会对表单的内容有所改变,看起来体验比较好。本文介绍自己使用jquery.validate以及bootstrap的tooltip打造一种气泡式表单校验的思路,如果你有一些个性化较强的表单校验需求,希望这篇文章能对你有些参考价值。
在线demo(点击下面链接页面中的保存按钮,或者改变表单元素的值都能触发校验):
demo相关的逻辑代码:
效果预览:
组件实现:
(有3个关联的文件,可通过以上链接查看)
其它事项:
1)本文提供的校验实现依赖jquery,jquery.validate,bootstrap,并采用seajs来做模块化管理;
2)本文的demo结合之前写的form组件来一起使用,form管理的相关文章有:
相关文档:
下面就来看看该如何实现这个气泡式的表单校验吧。
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调用时的方式,只用到了前面提到的这两个选项。
接下来就来看看实际实现时的一些要点。
2. 详细实现
1)从代码组织说起
本文实现主要包含三个文件:
核心的文件是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; } }));
这两个代码应该很好理解,因为各个部分的逻辑都已经单独抽出来封装了,细节可以逐一去阅读了解:
以上每个方法都比较简单,所以就不拆开来介绍了。
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相关的逻辑代码中,就看到实际的使用举例:
从这个举例也能看到,新的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这种已有的校验框架来完成个性化的表单校验功能思路,将来在碰到其它的个性化校验需求的时候,也完全可参照这个思路,尝试去做些统一的自定义组件,毕竟基于已有的成果去扩展比自己去造轮子,要来的更快更轻一些。本文提供的校验方式,使用起来还是挺爽的,也支持校验规则的增删改,方式同官方文档,欢迎使用并讨论相关的问题,我在项目中都用它,尤其在管理系统里面开发的时候,非常高效。
相关推荐
- 自卑的人容易患抑郁症吗?(自卑会导致抑郁吗)
-
Filephoto[Photo/IC]Lowself-esteemmakesusfeelbadaboutourselves.Butdidyouknowthatovert...
- 中考典型同(近)义词组(同义词考题)
-
中考典型同(近)义词组...
- BroadcastReceiver的原理和使用(broadcast-suppression)
-
一、使用中注意的几点1.动态注册、静态注册的优先级在AndroidManifest.xml中静态注册的receiver比在代码中用registerReceiver动态注册的优先级要低。发送方在send...
- Arduino通过串口透传ESP 13板与java程序交互
-
ESP13---是一个无线板子,配置通过热点通信Arduino通过串口透传ESP13板与java程序交互...
- zookeeper的Leader选举源码解析(zookeeper角色选举角色包括)
-
作者:京东物流梁吉超zookeeper是一个分布式服务框架,主要解决分布式应用中常见的多种数据问题,例如集群管理,状态同步等。为解决这些问题zookeeper需要Leader选举进行保障数据的强一致...
- 接待外国人英文口语(接待外国友人的英语口语对话)
-
接待外国人英文口语询问访客身份: MayIhaveyourname,please? 请问您贵姓? Whatcompanyareyoufrom? 您是哪个公司的? Could...
- 一文深入理解AP架构Nacos注册原理
-
Nacos简介Nacos是一款阿里巴巴开源用于管理分布式微服务的中间件,能够帮助开发人员快速实现动态服务发现、服务配置、服务元数据及流量管理等。这篇文章主要剖析一下Nacos作为注册中心时其服务注册与...
- Android面试宝典之终极大招(android面试及答案)
-
以下内容来自兆隆IT云学院就业部,根据多年成功就业服务经验,以及职业素养课程部分内容,归纳总结:18.请描述一下Intent和IntentFilter。Android中通过Intent...
- 除了Crontab,Swoole Timer也可以实现定时任务的
-
一般的定时器是怎么实现的呢?我总结如下:1.使用Crontab工具,写一个shell脚本,在脚本中调用PHP文件,然后定期执行该脚本;2.ignore_user_abort()和set_time_li...
- Spark源码阅读:DataFrame.collect 作业提交流程思维导图
-
本文分为两个部分:作业提交流程思维导图关键函数列表作业提交流程思维导图...
- 使用Xamarin和Visual Studio开发Android可穿戴设备应用
-
搭建开发环境我们需要做的第一件事情是安装必要的工具。因此,你需要首先安装VisualStudio。如果您使用的是VisualStudio2010,2012或2013,那么请确保它是一个专业版本或...
- Android开发者必知的5个开源库(android 开发相关源码精编解析)
-
过去的时间里,Android开发逐步走向成熟,一个个与Android相关的开发工具也层出不穷。不过,在面对各种新鲜事物时,不要忘了那些我们每天使用的大量开源库。在这里,向大家介绍的就是,在这个任劳任怨...
- Android事件总线还能怎么玩?(android实现事件处理的步骤)
-
顾名思义,AndroidEventBus是一个Android平台的事件总线框架,它简化了Activity、Fragment、Service等组件之间的交互,很大程度上降低了它们之间的耦合,使我们的代码...
- Android 开发中文引导-应用小部件
-
应用小部件是可以嵌入其它应用(例如主屏幕)并收到定期更新的微型应用视图。这些视图在用户界面中被叫做小部件,并可以用应用小部件提供者发布。可以容纳其他应用部件的应用组件叫做应用部件的宿主(1)。下面的截...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
推荐7个模板代码和其他游戏源码下载的网址
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
-
- 自卑的人容易患抑郁症吗?(自卑会导致抑郁吗)
- 中考典型同(近)义词组(同义词考题)
- WPF 消息传递简明教程(wpf messagebox.show)
- BroadcastReceiver的原理和使用(broadcast-suppression)
- Arduino通过串口透传ESP 13板与java程序交互
- zookeeper的Leader选举源码解析(zookeeper角色选举角色包括)
- 接待外国人英文口语(接待外国友人的英语口语对话)
- 一文深入理解AP架构Nacos注册原理
- Android面试宝典之终极大招(android面试及答案)
- 除了Crontab,Swoole Timer也可以实现定时任务的
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)