说到表单校验,第一个想起来的肯定是jquery的validate.js,该插件的确是很强大,用在项目中也很健壮,但是为什么我选择重新自己封装一个插件呢?
为什么要自己封装表单验证插件:
1、因为项目中用到的是sea.js,需要对插件进行封装,而楼主不知如何封装validate.js,和其连带的其他插件;
2、因为项目中不是所有的校验都是通过插件校验的,也要自己手动校验一部分,表单提交时不知如何提交;
3、插件功能越多,就意味着越大…
封装的表单验证如何调用?
1、引入jquery.min.js,因为表单中的语法不是原生的,是基于jquery的,因此引入jquery时必备的;
2、引入我们的插件form.js;
3、html中通过标签引用,例如<input type="text" name="phone" flag="false" id="phone" placeholder="请输入您的手机号" check="required isMobile" />
,其中id是必须的,check中的内容是你需要校验的项,flag="false"是是否通过校验的标识,接下来,我将进行详细讲解。
form.js插件代码详解?
(function ($) {
$.fn.extend({
"checkForm": function (options) {
var flag = true;//标志每一个输入框中所有检验规则是否执行
var root = this; //当前应用对象存入root
var pwd; //密码存储
var defaults = {
// 提示信息
tip_success: '<img src="../../xstatic/ximages/zhengque.png" />', //验证成功提示
loginname: { //html中的标签的id值
remote: "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>用户登录名已存在", //验证后的错误提示
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>用户名不能为空",
rangelength:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>用户名长度只能在 6-15位字符之间",
stringCheck:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>只能包括英文字母、数字和下划线 ",
reg_rangelength:/^[a-zA-Z0-9]{6,15}$/, //对应的正则校验
reg_stringCheck:/^[a-zA-Z][a-zA-Z0-9_]*$/
},
username: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>姓名不能为空",
rangelength : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>姓名长度只能在2-20位字符之间",
isChineseChar : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>姓名必须为汉字",
reg_rangelength:/^[\u4e00-\u9fa5]{2,10}$/,
reg_isChineseChar:/^[\u4E00-\u9FA5]+$/,
},
company: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>公司/企业名称不能为空"
},
yzm: {
remote: "<img src='../../xstatic/ximages/cuowu.png ' style='margin-right: 8px;'>验证码不正确",
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>验证码不能为空"
},
phone: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>手机号不能为空",
isMobile : "<img src='../../xstatic/ximages/cuowu.png ' style='margin-right: 8px;'>手机号码格式有误,请输入正确的手机号",
remote : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>手机号已注册,继续注册请与原账号解绑",
reg_isMobile:/^13[0-9]{1}[0-9]{8}$|14[0-9]{1}[0-9]{8}$|15[0-9]{1}[0-9]{8}$|17[0-9]{1}[0-9]{8}$|18[0-9]{1}[0-9]{8}$/
},
inviteid: {
remote: "<img src='../../xstatic/ximages/cuowu.png ' style='margin-right: 8px;'>邀请码录入不正确",
checkFigure:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>只能含有数字",
reg_checkFigure:/^\d+$/
},
confirmPassword: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>请再次输入密码",
equalTo:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>两次输入密码不一致"
},
plainPassword: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>请输入密码",
rangelength:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>密码长度只能在 6-15位字符之间",
stringCheck:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>只能包括英文字母、数字和下划线",
reg_rangelength:/^[a-zA-Z0-9]{6,15}$/,
reg_stringCheck:/^[a-zA-Z0-9_]*$/
},
place: {
rangelength : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>职位长度只能在2-15位字符之间",
reg_rangelength:/^[a-zA-Z0-9]{2,15}$/,
},
email: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>邮箱不能为空",
stringCheck:"<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>请输入正确的邮箱格式",
reg_stringCheck:/^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/
},
address: {
rangelength : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>地址长度只能在4-50位字符之间",
reg_rangelength:/^[a-zA-Z0-9]{4,50}$/,
},
businmark: {
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>营业执照注册号不能为空"
},
myfiles:{
required : "<img src='../../xstatic/ximages/tishi.png ' style='margin-right: 8px;'>请上传营业执照"
}
};
if (options) { //如果不为空就合并参数
$.extend(defaults, options)
}
// 文本框失去焦点时验证
$(":text,:password,textarea", root).each(function () {
$(this).blur(function () {
var _validate = $(this).attr("check");
if (_validate) { //如果输入框需要校验,则执行check()方法
check($(this), _validate, $(this).val());
}
})
});
// 验证方法
var check = function (obj, _match, _val) {
//obj为对应的需要校验的输入框
//match为html中check属性的属性值
//val为输入框的值
var id=obj.attr("id");//这里是为了取到对应的元素的校验值defaults[id]
var value=$.trim(_val);//防止空格
var arr = _match.split(" ");//校验项字符串转为数组
for(var i=0;i<arr.length;i++){
if(flag==true){ //flag控制是否进行下一项的校验,因此html中check="required isMobile"中的校验项有顺序,需要自己控制
switch (arr[i]) { //arr[i]为校验项
case 'required':
flag=value ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].required, false);
//校验必须字段,及时的更改flag状态,校验成功返回true,失败返回false,成功之后才会进行下一项的校验,失败,直接提示失败文案
break;//执行到此,case语句不再往下执行
case 'rangelength':
if(!value){ //针对非必填项,没有required的校验,所以一定要判断一下value是否为空,空的时候不执行以下的校验项,因为该项可为空
break;
}else{
flag=chk(value, defaults[id].reg_rangelength) ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].rangelength, false);
break;
}
case 'stringCheck':
if(!value){
break;
}else{
flag=chk(value, defaults[id].reg_stringCheck) ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].stringCheck, false);
break;
}
case 'pw1': //该校验项应为password的最后一项校验
flag="true";//flag标识
pwd = value; //实时储存
var confirmValue=$("#confirmPassword").val(); //确认密码
if(value==confirmValue){ //以下校验是为了防止密码和确认密码一致后,再去改动密码,而确认密码不会提示的问题
$("#confirmPassword").attr("flag","true");//当两者一致时,标记确认密码校验通过
showMsg($("#confirmPassword"), defaults.tip_success, true);
}else if(value!=confirmValue&&confirmValue){
$("#confirmPassword").attr("flag","false");//当两者不一致时,标记确认密码校验不通过
showMsg($("#confirmPassword"),defaults.confirmPassword.stringCheck, false);
}
break;
case 'pw2'://该校验项应为confirmPassword的最后一项校验
if(!value){
break;
}else{
flag=pwdEqual(value, pwd) ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].equalTo, false);
break;
}
case 'isChineseChar':
if(!value){
break;
}else{
flag=chk(value, defaults[id].reg_isChineseChar) ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].isChineseChar, false);
break;
}
case 'isMobile':
if(!value){
break;
}else{
flag=chk(value, defaults[id].reg_isMobile) ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].isMobile, false);
break;
}
case 'checkFigure':
if(!value){
break;
}else{
flag=chk(value, defaults[id].reg_checkFigure) ? showMsg(obj, defaults.tip_success, true) : showMsg(obj, defaults[id].checkFigure, false);
break;
}
defaults:
return true;
}
}else{ //flag==false时,一定校验不通过,
obj.attr("flag",false);
}
if(i==arr.length-1){ //当校验到最后一项时,需要将flag表示置为true,否则其他校验无法进入
//以下是需要调用接口才可验证的项,按照自己需求可就行改造
if(flag==true&&id=="phone"){ //校验手机号是否已注册
$.ajax({
type: "post",
async: false,
url: "http://www.baidu.com/register/checkPhone",
data: {phone: value},
dataType: "text",
success: function (data) {
if(data=="false"){
showMsg(obj, defaults[id].remote, false);
flag=false;
$(".send-yzm").css("color","rgba(0,0,0,.3)");
}else{ //手机号校验成功
$(".send-yzm").css("color","#313131");
}
}
});
}
if(flag==true&&id=="yzm"){ //校验验证码是否正确
var phone=$("#phone").val();
$.ajax({
type: "post",
async: false,
url: "http://www.baidu.com/register/checkRandom",
data: {yzm: value,phone:phone},
dataType: "text",
success: function (data) {
if(data=="false"){
showMsg(obj, defaults[id].remote, false);
flag=false;
}
}
});
}
if(flag==true&&id=="loginname"){ //校验验证码是否正确
if(value){
$.ajax({
type: "post",
async: false,
url: "http://www.baidu.com/register/checkLoginName",
data: {loginname: value},
dataType: "text",
success: function (data) {
if(data=="false"){
showMsg(obj, defaults[id].remote, false);
flag=false;
}
}
});
}else{
$(obj).next(".errormsg").remove();
}
}
if(flag==true&&id=="inviteid"){ //校验验证码是否正确
if(value){
$.ajax({
type: "post",
async: false,
url: "http://www.baidu.com/register/checkInvite",
data: {inviteid: value},
dataType: "text",
success: function (data) {
if(data=="false"){
showMsg(obj, defaults[id].remote, false);
flag=false;
}
}
});
}else{
$(obj).next(".errormsg").remove();
}
}
obj.attr("flag",flag);//当前校验项是否通过由flag进行控制
flag=true;//全局flag复位
}
}
};
//判断两次密码是否一致
var pwdEqual = function (val1, val2) {
return val1 == val2 ? true : false;
};
//正则验证
var chk = function (str, reg) {
return reg.test(str);
};
//显示信息
var showMsg = function (obj, msg, mark) {//文字显示的位置在此处控制
var id=obj.attr("id");
if(id=="phone"&&mark==false){
$(".send-yzm").css("color","rgba(0,0,0,.3)");
}
$(obj).next(".errormsg").remove();
var _html = "<span class='errormsg' style='font-size:14px;color:#ff3c00;margin-left:10px; '>" + msg + "</span>";
if(id=="yzm"){
$(obj).next().next(".errormsg").remove();
$(obj).next().after(_html);
}else{
$(obj).after(_html);
}
return mark;
}
}
})
})(jQuery);
总结:代码注释的很是详细,相信大家看完之后就会明白其原理,简单明了,可操作性强。但是仍然有几个地方需要提醒大家注意:
-
<form action="http://baidu.com" method="post" flag="true">
form表单需要指定flag标记,true表示表单可提交,false表示表单不可提,这是为了方便大家重写submit方法,可在方法中添加自己需要控制的东西,要是有插件不能校验的校验项,可通过判断form的flag是否为true,true的话再去判断,false的话直接提示插件校验结果。 -
<form action="http://baidu.com" method="post" flag="true">
默认的flag应为true,因为submit方法没有写在插件中,所以点击提交的时候需要我们去校验是否为空,因为插件中的事件都是在失去焦点时触发的,因此一旦输入框触发了失去焦点事件,插件一定做了校验,所以没有做检验的一定为空,提交方法如下:
function _onSubmit() {
$(":text,:password", $(".content-warp")).each(function () {
var flag=$(this).attr("flag");
//判断每个输入框的是否通过校验
var id=$(this).attr("id");
var value=$.trim($(this).val());
if(flag=="false"){ //如果没有进行填选
//一旦有一个未flase,form表单不可提交
$(".form1").attr("flag","false"); if(id!="loginname"&&id!="inviteid"&&id!="registerYZM"){
//这个为过滤掉不必填项
if(!value){
$(this).next(".errormsg").remove();
var _html = "<span class='errormsg' style='font-size:14px;color:#ff3c00;margin-left:10px; '>" + defaults[id].required + "</span>";
if(id=="yzm"){ $(this).next().next(".errormsg").remove();
$(this).next().after(_html);
}else{
$(this).after(_html);
}
}
}
}
});
}
.
3. <input type="text" name="phone" flag="false" id="phone" placeholder="请输入您的手机号" check="required isMobile" />
每一个校验项默认的flag应该为false,等校验成功后将该项flag置为true,
4. 最后提醒一句,一旦涉及到表单提交,最好写一个防止重复提交的方法,因为这是一个好的习惯。