jQuery.Validate.js验证大表单的优化
最近在项目中有遇到一个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验证大表单的优化的更多相关文章
- 使用jquery.validate.js插件进行表单里控件的验证
jsp中具体实现的代码: <%@ page language="java" contentType="text/html; charset=UTF-8" ...
- jquery.validate.js之自定义表单验证规则
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因
jquery.validate.js 验证表单时,在IE当中未验证就直接提交的原因 今天利用了jquery.validate.js来验证表单,发现在火狐.谷歌浏览器当中都可以进行验证,但是在IE系列浏 ...
- js验证form表单示例
js验证form表单示例 检测测试了js表单验证,无jQuery(简单的功能有时无需jQuery版本) js代码如下: <script type="text/javascript& ...
- 第十七篇 JS验证form表单
JS验证form表单 这节课做一个实际的,项目里会遇到的东西,例如登录页面,我们输入‘用户名’和‘密码’或者‘手机号’还有‘验证码’等等,它都会做一个前端验证,比如验证码,是6位有效数字组成,那么 ...
- jQuery Validate【强大的表单验证】
一.引入菜鸟教程提供的 1.14.0 版本下载地址:http://static.runoob.com/download/jquery-validation-1.14.0.zip <script ...
- 使用jquery validate结合zui作表单验证
1.引入jquery validate和zui <!-- jQuery (ZUI中的Javascript组件依赖于jQuery) --> <script src="${_b ...
- jquery validate如何不提交表单就做验证(ajax提交数据)
if($("#FromID").valid()){ $.ajax({ type:'post', url:'/CampaignOrderRelations/save', data:{ ...
- jquery.form.js(ajax表单提交)
Form插件地址: 官方网站:http://malsup.com/jQuery/form/ 翻译地址:http://www.aqee.net/docs/jquery.form.plugin/jquer ...
随机推荐
- 如何卸载掉eclipse中的插件
First-->Help->About Eclipse Second--> Third-->
- HDU 2239 polya计数 欧拉函数
这题模数是9937还不是素数,求逆元还得手动求. 项链翻转一样的算一种相当于就是一种类型的置换,那么在n长度内,对于每个i其循环节数为(i,n),但是由于n<=2^32,肯定不能直接枚举,所有考 ...
- 原生JS实现省市区(县)三级联动选择
原文地址→看过来 写在前面 前段时间写一个关于天气的东西,里面的省市区(县)城市选择让我很头疼,在网上搜索出来大都是借助插件或者第三方库,感觉这样做代码会很重,所以索性就把几种城市选择的方式实现一遍, ...
- JAVA多线程基础学习二:synchronized
本篇主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题,没错就是使用synchronized. 一.如何解决线程安全问题? 一般 ...
- 【LIbreOJ】#6256. 「CodePlus 2017 12 月赛」可做题1
[题意]定义一个n阶正方形矩阵为“巧妙的”当且仅当:任意选择其中n个不同行列的数字之和相同. 给定n*m的矩阵,T次询问以(x,y)为左上角的k阶矩阵是否巧妙.n,m<=500,T<=10 ...
- Python作业选课系统(第六周)
作业需求: 角色:学校.学员.课程.讲师.完成下面的要求 1. 创建北京.上海 2 所学校 2. 创建linux , python , go 3个课程 , linux\py 在北京开, go 在上海开 ...
- Go语言 7 并发编程
文章由作者马志国在博客园的原创,若转载请于明显处标记出处:http://www.cnblogs.com/mazg/ Go学习群:415660935 今天我们学习Go语言编程的第七章,并发编程.语言级别 ...
- 莫比乌斯反演第二弹 入门 Coprime Integers Gym - 101982B
题目链接:https://cn.vjudge.net/problem/Gym-101982B 题目大意: 给你(a,b)和(c,d)这两个区间,然后问你这两个区间中互素的对数是多少. 具体思路:和我上 ...
- NEO发行资产Token
NEO注册发行全局资产(Token 和 Share)功能已经在neo-gui里面集成,发行非常方便, 高级-注册资产 注册Token消耗GAS感人 4990 Gas 点击调用,获取交易ID为资产ID ...
- i春秋第二届春秋欢乐赛RSA256writeup
i春秋第二届春秋欢乐赛writeup 下载之后进行解压 发现四个文件 0x01看到题目是RSA的 又看到public.key 所以直接用kali linux的openssl 0x02可以看到e就是E ...