jQuery实现高度灵活的表单验证功能示例【无UI】


Posted in jQuery onApril 30, 2020

本文实例讲述了jQuery实现高度灵活的表单验证功能。分享给大家供大家参考,具体如下:

表单验证是前端开发过程中常见的一个需求,产品需求、业务逻辑的不同,表单验证的方式方法也有所区别。而最重要的是我们要清楚,表单验证的核心原则是——错误信息提示准确,并且尽可能少的打扰/干扰用户的输入和体验。

该插件依赖于jQuery,demo地址:https://github.com/CaptainLiao/zujian/tree/master/validator

基于以上原则,个人总结出表单验证的通用方法论:

为了使开发思路更加清晰,我将表单验证的过程分为两步:第一步,用户输入完验证当前输入的有效性;第二步,表单提交时验证整个表单。考虑如下布局:

<form action="">
  <ul>
    <li><label for="username">用户名</label>
      <input type="text" name="username" id="username" placeholder="用户名"/></li>
    <li>
      <label for="password">密码</label>
      <input type="text" name="password" id="password" placeholder="密码"/>
    </li>
    <li>
      <label for="password">确认密码</label>
      <input type="text" name="password2" id="password-confirm" placeholder="确认密码"/>
    </li>
    <li>
      <label for="phone">手机</label>
      <input type="text" name="mobile" id="phone"/>
    </li>
    <li>
      <label for="email">邮箱</label>
      <input type="text" name="email" id="email"/>
    </li>
  </ul>

  <button type="submit" id="submit-btn">提交</button>

</form>

一个较为通用的JS验证版本如下:

(function (window, $, undefined) {
  /**
   * @param {String}    $el       表单元素
   * @param {[Array]}    rules      自定义验证规则
   * @param {[Boolean]}   isCheckAll   表单提交前全文验证
   * @param {[Function]}  callback    全部验证成功后的回调
   * rules 支持四个字段:name, rule, message, equalTo
   */
  function Validator($el, rules, isCheckAll, callback) {
    var required = 'required';
    var params = Array.prototype.slice.call(arguments);
    this.$el = $el;
    this._rules = [
      {// 用户名
        username: required,
        rule: /^[\u4e00-\u9fa5\w]{6,12}$/,
        message: '不能包含敏感字符'
      }, {// 密码
        password: required,
        rule: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z_@]{6,20}$/,
        message: '只支持数字字母下划线,且不为纯数字或字母'
      }, {// 重复密码
        password2: required,
        rule: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z_@]{6,20}$/,
        message: '只支持数字字母下划线,且不为纯数字或字母',
        equalTo: 'password'
      }, {// 手机
        mobile: required,
        rule: /^1[34578]\d{9}$/,
        message: '请输入有效的手机号码'
      }, {// 验证码
        code : required,
        rule: /^\d{6}$/,
        message: '请输入6位数字验证码'
      }, {// 邮箱
        email : required,
        rule: /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/,
        message: '请输入正确的邮箱'
      }
    ];
    this.isCheckAll = false;
    this.callback = callback;
    // 合并参数
    this._rules = this._rules.concat(params[1]);
    if(params[2]) {
      if(typeof params[2] == 'function') {
        this.callback = params[2];
      }else {// 提交表单时是否开启全部验证
        this.isCheckAll = params[2];
      }
    }
    // 用于存储合去重后的参数
    this.rules = [];
  }

  Validator.prototype._getKey = function (obj) {
    var k = '';
    for(var key in obj) {
      if(obj.hasOwnProperty(key)) {
        if( key !== 'rule' && key !== 'message' && key !== 'equalTo') {
          k = key;
        }
      }
    }
    return k;
  };
  /**
   * 数组对象重复数据进行合并,后面的覆盖前面的
   */
  Validator.prototype.filterRules = function (arrObj) {
    var _this = this,
      h = {},
      res = [],
      arrObject = this._rules;
    $.each(arrObject, function (i, item) {
      var k = _this._getKey(item);
      try {
        if(!h[k] && h[k] !== 0) {
          h[k] = i;
          res.push(item);
        }else {
          res[h[k]] = $.extend(res[h[k]], item);
        }
      }catch(e) {
        throw new Error('不是必填')
      }
    });
    this.rules = res;
  };

  Validator.prototype.check = function () {
    var _this = this;
    $.each(_this.rules, function (i, item) {
      var key = _this._getKey(item),
        reg = item.rule,
        equalTo = item.equalTo,
        errMsg = item.message;

      _this.$el.find('[name='+key+']')
        .on('blur', function () {
          var $this = $(this),
            errorMsg = '',
            val = $this.val(),
            ranges = reg.toString().match(/(\d*,\d*)/),
            range = '',
            min = 0,
            max = 0,
            placeholderTxt = $(this).attr("placeholder") ? $(this).attr("placeholder") : '信息';

          // 定义错误提示信息
          if(val && val != 'undefined') { // 值不为空

            if(ranges) { // 边界限定
              range = ranges[0];
              min = range.split(',')[0] ? range.split(',')[0].trim() : 0;
              max = range.split(',')[1] ? range.split(',')[1].trim() : 0;
              if(val.length < min || val.length > max) { // 处理边界限定的情况
                if(min && max) {
                  errorMsg = '<span class="error-msg">请输入'+min+'-'+max+'位'+placeholderTxt+'</span>';
                }else if(min) {
                  errorMsg = '<span class="error-msg">最少输入'+min+'位'+placeholderTxt+'</span>';
                }else if(max) {
                  errorMsg = '<span class="error-msg">最多输入'+max+'位'+placeholderTxt+'</span>';
                }
              }else { // 边界正确但匹配错误
                errorMsg = '<span class="error-msg">'+errMsg+'</span>';

              }
            }else { // 没有边界限定
              errorMsg = '<span class="error-msg">'+errMsg+'</span>';
            }

            if(equalTo) {
              var equalToVal = _this.$el.find('[name='+equalTo+']').val();
              if(val !== equalToVal) {
                errorMsg = '<span class="error-msg">两次输入不一致,请重新输入</span>';
              }
            }

          } else { // 值为空
            errorMsg = '<span class="error-msg">请输入'+placeholderTxt+'</span>'
          }
          if($('.error-msg').length > 0) return;

          // 验证输入,显示提示信息
          if(!reg.test(val) || (equalTo && val !== equalToVal)) {
            if($this.siblings('.error-msg').length == 0) {
              $this.after(errorMsg)
                .siblings('.error-msg')
                .hide()
                .fadeIn();
            }
          }else {
            $this.siblings('.error-msg').remove();
          }
        })
        .on('focus', function () {
          $(this).siblings('.error-msg').remove();
        })
    });

  };
  Validator.prototype.checkAll = function () {
    var _this = this;
    if(_this.isCheckAll) {
      _this.$el.find('[type=submit]')
        .click(function () {
          _this.$el.find('[name]').trigger('blur');
          if($('.error-msg').length > 0) {
            console.log('有错误信息');
            return false;
          }else {
            console.log('提交成功');
            _this.callback();
          }
        });
      return false;
    }
  };
  Validator.prototype.init = function () {
    this.filterRules();
    this.check();
    this.checkAll();
  };
  $.fn.validator = function (rules, isCheckAll, callback) {
    var validate = new Validator(this, rules, isCheckAll, callback);
    return validate.init();
  };
})(window, jQuery, undefined);

你可以这样使用:

var rules = [
    {// 用户名
      username: 'required',
      rule: /^[\u4e00-\u9fa5\d]{6,12}$/,
      message: '只支持数字loo2222'
    },
    {// 密码
      password: 'required',
      rule: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z_@]{6,20}$/,
      message: 'mimmimmia'
    },
    {// 重复密码
      password2: 'required',
      rule: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z_@]{6,20}$/,
      message: '只支持数字字母下划线,不能为纯数字或字母2222',
      equalTo: 'password'
    },
    {// 座机
      telephone : 'required',
      rule: /^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+$/,
      message: '请输入正确的座机'
    }
  ];
  $('form').validator(rules, true)
jQuery 相关文章推荐
jQuery实现文章图片弹出放大效果
Apr 06 jQuery
jQuery实现动态生成表格并为行绑定单击变色动作的方法
Apr 17 jQuery
jQuery插件开发发送短信倒计时功能代码
May 09 jQuery
jQuery Pagination分页插件_动力节点Java学院整理
Jul 17 jQuery
javascript+jQuery实现360开机时间显示效果
Nov 03 jQuery
jquery无缝图片轮播组件封装
Nov 25 jQuery
layui+jquery支持IE8的表格分页方法
Sep 28 jQuery
jQuery 淡入/淡出效果函数用法分析
May 19 jQuery
Jquery cookie插件实现原理代码解析
Aug 04 jQuery
js和jquery判断数据类型的4种方法总结
Aug 28 jQuery
jQuery-App输入框实现实时搜索
Nov 19 jQuery
jQuery实现动态操作table行
Nov 23 jQuery
jQuery插件simplePagination的使用方法示例
Apr 28 #jQuery
jquery检测上传文件大小示例
Apr 26 #jQuery
jquery实现轮播图特效
Apr 12 #jQuery
用jQuery实现抽奖程序
Apr 12 #jQuery
jquery实现两个div中的元素相互拖动的方法分析
Apr 05 #jQuery
jQuery 图片查看器插件 Viewer.js用法简单示例
Apr 04 #jQuery
jQuery实现鼠标放置名字上显示详细内容气泡提示框效果的方法分析
Apr 04 #jQuery
You might like
很实用的一个完整email发送程序
2006/10/09 PHP
php表单转换textarea换行符的方法
2010/09/10 PHP
IP攻击升级,程序改进以对付新的攻击
2010/11/23 PHP
php中serialize序列化与json性能测试的示例分析
2013/04/27 PHP
AJAX的跨域访问-两种有效的解决方法介绍
2013/06/22 PHP
phpmyadmin打开很慢的解决方法
2014/04/21 PHP
ThinkPHP使用心得分享-ThinkPHP + Ajax 实现2级联动下拉菜单
2014/05/15 PHP
PHP不用递归遍历目录下所有文件的代码
2014/07/04 PHP
php视频拍照上传头像功能实现代码分享
2015/10/08 PHP
php curl 模拟登录并获取数据实例详解
2016/12/22 PHP
PHP实现深度优先搜索算法(DFS,Depth First Search)详解
2017/09/16 PHP
详解如何实现Laravel的服务容器的方法示例
2019/04/15 PHP
javascript读取RSS数据
2007/01/20 Javascript
extJs 下拉框联动实现代码
2010/04/09 Javascript
javascript循环变量注册dom事件 之强大的闭包
2010/09/08 Javascript
jquery1.5.1中根据元素ID获取元素对象的代码
2011/04/02 Javascript
javascript简单事件处理和with用法介绍
2013/09/16 Javascript
javascript常用函数归纳整理
2014/10/31 Javascript
AngularJS初始化过程分析(引导程序)
2014/12/06 Javascript
JavaScript知识点整理
2015/12/09 Javascript
NodeJs——入门必看攻略
2016/06/27 NodeJs
判断输入的字符串是否是日期格式的简单方法
2016/07/11 Javascript
jquery 获取索引值在一定范围的列表方法
2018/01/25 jQuery
使用相同的Apache实例来运行Django和Media文件
2015/07/22 Python
分享Python文本生成二维码实例
2016/01/06 Python
Python网站验证码识别
2016/01/25 Python
django 微信网页授权登陆的实现
2019/07/30 Python
python英语单词测试小程序代码实例
2019/09/09 Python
tensorflow 固定部分参数训练,只训练部分参数的实例
2020/01/20 Python
如何打印出当前源文件的文件名以及源文件的当前行号
2015/04/05 面试题
医院护士见习期自我鉴定
2014/04/10 职场文书
小学班级特色活动方案
2014/08/31 职场文书
铅球加油稿100字
2014/09/26 职场文书
2016春季运动会通讯稿
2015/07/18 职场文书
解决springboot druid数据库连接失败后一直重连的方法
2022/04/19 Java/Android
Python使用pyecharts控件绘制图表
2022/06/05 Python