最近在项目中有遇到一个Form表单中有200多个标签。在提交表单时网页会出现等待时间很长,甚至会出现网页奔溃的情况。

主要的原因是因为在使用jQuery.Validate.js进行Form验证的时候会花销大量时间。这些时间主要用在两个地方:

1.表单中标签的检查对应jQuery.Validate.js中checkForm()方法。

2.检查完标签后需要显示错误或成功信息对应jQuery.Validate.js中ShowErrors()方法。

先前我们是用的jQuery.Validate.js-1.8.0版本,我更新到最新的jQuery.Validate.js-1.15.1版本,发现验证时间没有得到明显的优化。

反而会与之前的版本会有冲突,冲突的地方在无法验证隐藏的控件,例如用了第三方的HTML编辑框插件,后面会隐藏一个textarea控件,之前低版本的会检测到这个,但是新版本的会忽略。问题在于新版本的js默认会跳过页面中不可见的元素。

1.8.0版本的ignore:[] 这里改为“.hidden”在checkForm()时会默认过滤掉页面中所有的不可见元素。

这是1.15.1种checkForm的方法:

checkForm: function() {
this.prepareForm();
for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
this.check( elements[ i ] );
}
return this.valid();
},
elements: function() {
var validator = this,
rulesCache = {}; // Select all valid inputs inside the form (no submit or reset buttons)
return $( this.currentForm )
.find( "input, select, textarea, [contenteditable]" )
.not( ":submit, :reset, :image, :disabled" )
.not( this.settings.ignore )//在这个地方会对隐藏元素进行过滤,返回的elements会少了很多隐藏的元素。
.filter( function() {
var name = this.name || $( this ).attr( "name" ); // For contenteditable
if ( !name && validator.settings.debug && window.console ) {
console.error( "%o has no name assigned", this );
} // Set form expando on contenteditable
if ( this.hasAttribute( "contenteditable" ) ) {
this.form = $( this ).closest( "form" )[ 0 ];
} // Select only the first element for each name, and only those with rules specified
if ( name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
return false;
} rulesCache[ name ] = true;
return true;
} );
},

这种处理的确可以减少很多不必要元素的check。但是经过测试这里的时间提升并不是十分明显。

但是这样处理后反而使得项目出现了不兼容的问题,因为像HTML编辑框等需要验证的背后隐藏元素也会被隐藏。

出于项目的需要,这里我将这个参数defaults中的ignore参数改为了input[type="hidden"]这样解决了兼容的问题。因为这个只对<input>标签中设置了"type=hidden"的元素忽略检查。

说了这么多并没有提到如何提升验证性能的方面。下面讨论下,由于本人也是小菜,希望大神勿喷。

上面有提到验证所花销的时间主要花在两个函数上,那么我们就从这两个函数说起:

1.checkForm().

从上面其实我们已经看出来了,将ignore设置值从而过滤掉一些隐藏的元素本身就是一种对checkForm()函数执行的优化。但是这里并没有起到实质性的作用,因为往往表单中隐藏的元素其实并不是很多,想要得到更大的提升应该是把页面中显示出来但是又不需要验证的标签进行过滤,真正做到只去check需要check的标签元素。这里网上有一种方法就是给每个不需要Check的元素标签添加一个类似于“class='validate-ignore'”这样的类,然后在elements()方法中把这样不需要验证的元素也过滤掉。这种做法我并没有去实践,因为项目中表单太多,这样一个个去添加新的class显的有点不现实。有兴趣的朋友可以去研究一下。

2.showErrors().

这个方法之所以会花销大量的时间。因为这个方法会使得HTML DOM树发生改变,来显示和修改错误或正确的提示信息。

原生的showErrors方法如下

默认页面中每个需要验证的elment都会经过这个else分支去执行defaultShowErrors()函数,而这个函数就是改变DOM树结构的入口。所以我们在这里新增一个判断的逻辑会提升不少的时间。新增判断如下:

showErrors: function( errors ) {
if ( errors ) {
var validator = this; // Add items to error list and map
$.extend( this.errorMap, errors );
this.errorList = $.map( this.errorMap, function( message, name ) {
return {
message: message,
element: validator.findByName( name )[ 0 ]
};
} ); // Remove items from success list
this.successList = $.grep( this.successList, function( element ) {
return !( element.name in errors );
} );
}
if ( this.settings.showErrors ) {
this.settings.showErrors.call( this, this.errorMap, this.errorList );
} else {
var anyElementsNeedUpdate = false; //参数表示是否需要去更新DOM树中的元素
for (var i = 0; i < this.errorList.length; i++) {
if (!$(this.errorList[i].element).hasClass(this.settings.errorClass)) {
anyElementsNeedUpdate = true;//1.当之前验证有错误的元素已经修改正确即没有了这个errorClass,需要去更新element
break;
}
} if (!anyElementsNeedUpdate) {
for (var i = 0; i < this.successList.length; i++) {
if ($(this.successList[i]).hasClass(this.settings.errorClass)) {
anyElementsNeedUpdate = true;//2.当之前验证成功的元素现在含有这个errorClass,需要去更新element
break;
}
}
} if (anyElementsNeedUpdate) {//如果有上面两种情况之一都需要去更新DOM元素,否则不应该去调用defaultShowErrors();
this.defaultShowErrors();
}
}
},

从这个可以明显的看出,checkForm()函数时间没有太大的变化。但是showErrors()时间变成了之前的十分之一。

经过测试这个修改对验证功能是没有影响的,而且性能也提升了不少。

参考:http://stackoverflow.com/questions/5542014/jquery-validate-large-forms-script-running-slowly

jQuery.Validate.js验证大表单的优化的更多相关文章

  1. 使用jquery.validate.js插件进行表单里控件的验证

    jsp中具体实现的代码: <%@ page language="java" contentType="text/html; charset=UTF-8" ...

  2. jquery.validate.js之自定义表单验证规则

    <html> <head> <meta http-equiv="Content-Type" content="text/html; char ...

  3. jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因

    jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因 今天利用了jquery.validate.js来验证表单,发现在火狐.谷歌浏览器当中都可以进行验证,但是在IE系列浏 ...

  4. js验证form表单示例

    js验证form表单示例 检测测试了js表单验证,无jQuery(简单的功能有时无需jQuery版本) js代码如下:   <script type="text/javascript& ...

  5. 第十七篇 JS验证form表单

    JS验证form表单   这节课做一个实际的,项目里会遇到的东西,例如登录页面,我们输入‘用户名’和‘密码’或者‘手机号’还有‘验证码’等等,它都会做一个前端验证,比如验证码,是6位有效数字组成,那么 ...

  6. jQuery Validate【强大的表单验证】

    一.引入菜鸟教程提供的 1.14.0 版本下载地址:http://static.runoob.com/download/jquery-validation-1.14.0.zip <script ...

  7. 使用jquery validate结合zui作表单验证

    1.引入jquery validate和zui <!-- jQuery (ZUI中的Javascript组件依赖于jQuery) --> <script src="${_b ...

  8. jquery validate如何不提交表单就做验证(ajax提交数据)

    if($("#FromID").valid()){ $.ajax({ type:'post', url:'/CampaignOrderRelations/save', data:{ ...

  9. jquery.form.js(ajax表单提交)

    Form插件地址: 官方网站:http://malsup.com/jQuery/form/ 翻译地址:http://www.aqee.net/docs/jquery.form.plugin/jquer ...

随机推荐

  1. cmd窗口关闭 -----window小技巧!

    前沿 平时开发的时候经常用到windows  的命令行工具来启动程序  或是 查看本地数据库的信息 : 经常的手动关闭 ,对于我这种,能用键盘完成的就坚决不用鼠标的人是多么痛苦. 所以在此罗列了一些命 ...

  2. oracle的小语句

    select * from v$nls_parameters; 查询数据库中现在的常量 alter session set NLS_DATE_FORMAT='yyyy-mm-dd'; 更改日期显示方式

  3. HDU 3507 单调队列 斜率优化

    斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...

  4. docker-compose写法收集

    version: '3.3' services: php: image: docker.ksyun.com/php7.:latest volumes: - ./env/log/apps:/data/l ...

  5. 【CODEVS】1033 蚯蚓的游戏问题

    [算法]网络流-最小费用最大流(费用流) [题解]与方格取数2类似 在S后添加辅助点S_,限流k 每条边不能重复走,限流1 #include<cstdio> #include<alg ...

  6. 【POJ】3233 Matrix Power Series

    [算法]二分+矩阵快速幂 [题意]给定矩阵A和整数k,MOD,求A^0+A^1+A^2+...+A^k. [题解] 定义题目要求的答案为f(n),即: $$f_n=\sum_{i=0}^{n}A^i$ ...

  7. Oracle数据库语句

    Oracle数据库语句 ORACLE支持五种类型的完整性约束 NOT NULL (非空)--防止NULL值进入指定的列,在单列基础上定义,默认情况下,ORACLE允许在任何列中有NULL值. CHEC ...

  8. 【leetcode 简单】 第八题 删除排序数组中的重复项

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例 1 ...

  9. 24、简述Python的深浅拷贝以及应用场景

    深浅拷贝的原理 深浅拷贝用法来自copy模块. 导入模块:import copy 浅拷贝:copy.copy 深拷贝:copy.deepcopy 字面理解:浅拷贝指仅仅拷贝数据集合的第一层数据,深拷贝 ...

  10. git@oschina.net源代码管理使用日记【转】

    转自:https://www.cnblogs.com/Juvy/p/3556902.html git的优势: 1 可以创建分支: 2 版本控制是基于每一次提交的,而不需要考虑每次提交了多少个文件. 下 ...