JavaScript表单验证开发
本文介绍了一种基于JavaScript和jQuery的表单验证实现方案。通过自定义add和get方法,将表单元素与验证规则以数组形式绑定。核心逻辑利用二维数组缓存验证配置,并通过merges函数统一处理单个或批量元素的检测流程,支持多种内置验证类型及参数传递。
JavaScript表单验证实现思路与核心代码解析
本文分享了一段JavaScript实现表单验证的具体代码示例,供读者参考学习。
在线演示地址为:http://www.hui12.com/nbin/csdn/jsInput/demo.html
具体运行效果如下图所示:

/* 验证类型
testName: "验证用户",
testPassword: "密码",
testPhone: "手机号码",
testQQ: "验证QQ",
testLength: "验证是否在指定长度内", //3个参数,最小和最大
testEmail: "验证邮箱",
testSame: "两个元素比较是否相同", //接受两个参数
testWX: "验证微信昵称",
testPlane: "验证座机",
testManCard: "验证身份证"
*/
/* 使用方法
* 创建实例对象 var a = new testInput();
* 传入dom-JQ对象和对应的检测的方法
* a.add( [$(".testName"),"testName"] ),以数组形式
* 可以接受2次数组多传 a.add([[$(".testName"),"testName"], [$(".testName"),"testName"]])
* 检测方法
* a.get( $(".testName") ) 获取单个结果,返回结果为JSON {result:'结果', text:'提示'}
* a.get( [$(".testName"), $(".testName")] ) 获取指定结果 返回结果为数组 [{obj:'',result:'',txt:''}, {obj:'',result:'',txt:''}]
* a.get() 如果不传入参数,则获取所有结果,不包含特殊验证 testLength, testSame
* 特殊检测
* 检测是字节长度是否在指定范围内 a.get( [$(".testLength"), min, max] ) 最小值最大值,数字类型
* 检测两个输入内容是否一致(2次密码确认) a.get([$(".testSama"), $(".testSama"), "same"]) 前两个为比较对象,第三个为固定必填参数
*/
(function(window, $){
var proto = {
testName: function($obj){
var str = $obj.val();
if( !this.checkNormal(str) ){
return {
result: false,
txt: "由字母,数字、下划线组成"
}
};
if( !this.checkLength(str,6,20) ){
return {
result: false,
txt: "长度在6-20个字符以内"
}
};
if( !this.checkFirstA(str) ){
return {
result: false,
txt: "第一个字符不能为数字"
}
};
return {
result: true,
txt: ""
}
},
testPassword: function($obj){
return this.testName($obj);
},
testPhone: function($obj){
var str = $obj.val();
var re = /^1\d{10}$/;
if( re.test(str) ){
return {
result: true,
txt: ""
}
}else{
return {
result: false,
txt: "手机号码由11位数字组成"
}
}
},
testQQ: function($obj){
var str = $obj.val();
var re = /^\d{5,10}$/;
if( re.test(str) ){
return {
result: true,
txt: ''
}
}else{
return {
result: false,
txt: "5~10位数字"
}
}
},
testLength: function($obj, a, b){
if( this.checkLength($obj.val(),a,b) ){
return {
result: true
}
}else{
return {
result: false
}
}
},
testEmail: function($obj){
var re = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/;
var str = $obj.val();
if( re.test(str) ){
return {
result: true,
txt: ""
};
}else{
return {
result: false,
txt: "邮箱格式不正确"
}
};
},
testSame: function($obj1, $obj2){
if( $obj1.val() == $obj2.val() ){
return {
result: true,
txt: ""
}
}else{
return {
result: false,
txt: "不一致"
}
}
},
testWX: function($obj){
var str = $obj.val();
var reg = /^[a-z_\d]+$/;
if( reg.test(str) ){
return {
result: true,
txt: ""
};
}else{
return {
result: false,
txt: ""
}
}
},
testPlane: function($obj){
var str = $obj.val();
var reg = /^\d{3,4}-\d{5,8}$/;
if( reg.test(str) ){
return {
result: true,
txt: ""
}
}else{
return {
result: false,
txt: "格式为:010-1234567"
}
}
},
testManCard: function($obj){
var str = $obj.val();
var reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
if( reg.test(str) ){
return {
result: true,
}
}else{
return {
result: false,
text: "请输入正确的身份证号码"
}
}
},
/*
* 检测方法
*/
checkEmpty: function(str){
if( str.trim() == '' ){
return false;
}else{
return true;
}
},
//检测第一个字母是否为数字
checkFirstA: function(str){
var first = str.charAt(0);
if( /\d/.test(first) ){
return false;
}else{
return true;
}
},
//检测数字+字母
checkNormal: function(str){
var reg = /^(([a-z]+[0-9]+)|([0-9]+[a-z]+))[a-z0-9]*$/i;
if( reg.test(str) ){
return true;
}else{
return false;
}
},
//检测是否在规范长度内
checkLength: function(str,a,b){
var min = a || 6;
var max = b || 20;
var length = str.length;
if( length>=a && length <= b ){
return true;
}else{
return false;
}
},
//
add: function(arr){
!this.cache && (this.cache = []);
var isTwo = $.isArray(arr[0]);
if( isTwo ){
this.cache = this.cache.concat(arr);
}else{
this.cache.push(arr);
};
return this;
},
get: function(){
var This = this;
var args = arguments;
if( args.length === 0 ){
//检测所有, 返回数组结果
var tmp = [];
$.each(This.cache, function(i, val) {
var newArr = [].concat(val);
newArr.splice(1,1);
tmp.push( newArr );
});
return merges(tmp,10);
}else{
if( $.isArray(args[0]) ){ //[obj,obj,obj]
var tmp = [];
// 1.一个检测,带参数2,3 [obj,2,3]
// 2、一个检测,和另外一个是否相等 [obj,obj,'same']
// 3、多个检测,返回多个结果. [obj,obj],又可能出现上面2种情况
if( !isNaN(args[0][1]) || !isNaN(args[0][2]) ){
tmp.push(args[0]);
return merges(tmp, 1);
};
if( args[0][2] == 'same' ){
args[0].splice(2,1);
tmp.push(args[0]);
return merges(tmp, 1);
};
$.each(args[0], function(i, val) {
if( $.isArray(val) ){
tmp.push(val);
}else{
tmp.push([val]);
};
});
return merges(tmp);
}else{
//常规
return merges([[args[0]]], 1);
}
};
function merges(arr, one){ //arr = [ [obj,a,b], [obj] ]
var result = [];
$.each(arr, function(i, val){
var oldName = val[0][0];
var tName;
$.each(This.cache, function(i2,val2) {
if( oldName == val2[0][0] ){
tName = val2[1];
return false;
};
});
var r;
if( one == 10){
if( tName == "testLength" || tName == "testSame" ){
r = {
tName: "请单独获取"
};
}else{
r = This[tName].apply(This, val);
};
}else{
r = This[tName].apply(This, val);
};
if( one==1 ){
result.push(r);
return false;
};
r.obj = val[0];
result.push( r );
});
return one==1 ? result[0] : result;
};
}
};
function Test(){
return this;
};
Test.prototype = proto;
Test.prototype.constructor = Test;
window.Test = Test;
})(window, jQuery)
接下来重点解析add和get这两个核心方法的实现逻辑。
验证机制将表单元素与对应的规则进行绑定,存储结构采用数组形式,即【表单对象,规则名称】。
add: function(arr){
!this.cache && (this.cache = []);
var isTwo = $.isArray(arr[0]);
if( isTwo ){
this.cache = this.cache.concat(arr);
}else{
this.cache.push(arr);
};
return this;
}
使用cache变量来保存已注册的验证配置。isTwo变量用于判断传入的数据是否为二维数组,若为二维数组则表示需要传递多个值。
get方法的实现逻辑如下。
var This = this;
var args = arguments;
if( args.length === 0 ){
//检测所有, 返回数组结果
var tmp = [];
$.each(This.cache, function(i, val) {
var newArr = [].concat(val);
newArr.splice(1,1);
tmp.push( newArr );
});
return merges(tmp,10);
}
当未传入参数时,该方法会获取所有已注册的验证结果,所有执行逻辑均在merges函数内部完成。merges函数的第一个参数是检测元素,其结构为二维数组,例如[ [obj,a,b], [obj]]。由于存在带有特殊参数的检测项,内部的一维数组实际上由检测元素和所需参数组成。第二个参数用于标识特殊参数,后续代码通过判断该参数来确定是否执行全部检测。代码中使用splice截取第二个参数(即检测方法名,后续不再需要),截取后的数组结构变为【dom元素,参数】。
}else{
if( $.isArray(args[0]) ){ //[obj,obj,obj]
var tmp = [];
// 1.一个检测,带参数2,3 [obj,2,3]
// 2、一个检测,和另外一个是否相等 [obj,obj,'same']
// 3、多个检测,返回多个结果. [obj,obj],又可能出现上面2种情况
if( !isNaN(args[0][1]) || !isNaN(args[0][2]) ){
tmp.push(args[0]);
return merges(tmp, 1);
};
if( args[0][2] == 'same' ){
args[0].splice(2,1);
tmp.push(args[0]);
return merges(tmp, 1);
};
$.each(args[0], function(i, val) {
if( $.isArray(val) ){
tmp.push(val);
}else{
tmp.push([val]);
};
});
return merges(tmp);
}else{
//常规
return merges([[args[0]]], 1);
}
};
代码中使用$.isArray(args[0])判断第一个参数是否为数组。如果不是数组,则视为dom对象,此时执行merges([[args[0]]], 1),将第一个参数包装为二维数组,原因如前文所述;第二个参数设为1,用于后续结果判断,若为1则直接返回JSON格式的结果。当判断为真(即参数为数组)时,内部包含三种情况,分别对应不同的备注说明。
function merges(arr, one){ //arr = [ [obj,a,b], [obj] ]
var result = [];<span style="white-space:pre"> </span>//返回结果
$.each(arr, function(i, val){
var oldName = val[0][0];<span style="white-space:pre"> </span>//val为1次数组,得到源生dom对象
var tName;<span style="white-space:pre"> </span>//执行方法名字
$.each(This.cache, function(i2,val2) {
if( oldName == val2[0][0] ){<span style="white-space:pre"> </span>//如果传入dom和cache已保存的dom一样,则获取dom执行方法
tName = val2[1];
return false;
};
});
var r;
if( one == 10){<span style="white-space:pre"> </span>//全部获取,对特殊检测做特殊处理
if( tName == "testLength" || tName == "testSame" ){
r = {
tName: "请单独获取"
};
}else{
r = This[tName].apply(This, val);
};
}else{<span style="white-space:pre"> </span>//获取单个检测结果
r = This[tName].apply(This, val);
};
if( one==1 ){<span style="white-space:pre"> </span>//如果为1,则只单个检测,结果为[{}],然后跳出
result.push(r);
return false;
};
r.obj = val[0];<span style="white-space:pre"> </span>//没有执行1的判断,说明是多个元素检测,手动增加一个obj属性,方便返回值查询,结果为[{},{}...]
result.push( r );
});
return one==1 ? result[0] : result;<span style="white-space:pre"> </span>//针对传入参数返回不同结果
};
若需深入学习,可参考以下两个相关专题:jquery表单验证大全、JavaScript表单验证大全。
以上就是本文的全部内容,希望能为读者的学习提供有益帮助,同时也欢迎大家继续支持本站。
JS动态构建复杂嵌套JSON对象的方法
2026-11-05 15:41:52
JS负数取余为什么是负数?详解余数与模运算区别
2026-11-05 13:34:41
JS 解压出现乱码或报错怎么解决?
2026-11-05 12:32:38
JS 中 startsWith、indexOf 与正则判断字符串前缀的对比
2026-11-04 22:19:43
JS解析Excel后怎么将数据转换为JSON格式
2026-11-04 20:58:28
