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插件FusionWidgets实现的Bulb图效果示例【附demo源码下载】
Mar 23 jQuery
如何编写jquery插件
Mar 29 jQuery
简单实现jQuery弹幕效果
May 06 jQuery
jQuery动态追加页面数据以及事件委托详解
May 06 jQuery
基于jQuery选择器之表单对象属性筛选选择器的实例
Sep 19 jQuery
jquery自定义显示消息数量
Dec 19 jQuery
详解jQuery中的isPlainObject()使用方法
Feb 27 jQuery
jquery实现动态添加附件功能
Oct 23 jQuery
jQuery动态操作表单示例【基于table表格】
Dec 06 jQuery
jQuery+vue.js实现的多选下拉列表功能示例
Jan 15 jQuery
jquery添加div实现消息聊天框
Feb 08 jQuery
多种类型jQuery网页验证码插件代码实例
Jan 09 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
异步加载技术实现当滚动条到最底部的瀑布流效果
2014/09/16 PHP
php去除字符串中空字符的常用方法小结
2015/03/17 PHP
详解PHP文件的自动加载(autoloading)
2018/02/04 PHP
关于Blog顶部的滚动导航条代码
2006/09/25 Javascript
使用自定义setTimeout和setInterval使之可以传递参数和对象参数
2009/04/24 Javascript
跨浏览器开发经验总结(四) 怎么写入剪贴板
2010/05/13 Javascript
js操作iframe父子窗体示例
2014/05/22 Javascript
node.js中的fs.futimes方法使用说明
2014/12/17 Javascript
JS简单获取当前年月日星期的方法示例
2017/02/07 Javascript
JS实现复制功能
2017/03/01 Javascript
浅谈Angular HttpClient简单入门
2018/05/04 Javascript
解决vue中使用Axios调用接口时出现的ie数据处理问题
2018/08/13 Javascript
Vue请求JSON Server服务器数据的实现方法
2018/11/02 Javascript
JS严格模式原理与用法实例分析
2020/04/27 Javascript
JS变量提升原理与用法实例浅析
2020/05/22 Javascript
微信小程序自定义扫码功能界面的实现代码
2020/07/02 Javascript
Python 除法小技巧
2008/09/06 Python
TensorFlow模型保存和提取的方法
2018/03/08 Python
Python面向对象程序设计多继承和多态用法示例
2019/04/08 Python
python中threading开启关闭线程操作
2020/05/02 Python
Python实现七个基本算法的实例代码
2020/10/08 Python
python 实现数据库中数据添加、查询与更新的示例代码
2020/12/07 Python
html5 offlline 缓存使用示例
2013/06/24 HTML / CSS
HTML5自定义属性前缀data-及dataset的使用方法(html5 新特性)
2017/08/24 HTML / CSS
bonprix荷兰网上商店:便宜的服装、鞋子和家居用品
2020/07/04 全球购物
系统管理员的职责包括那些?管理的对象是什么?
2016/09/20 面试题
建龙钢铁面试总结
2014/04/15 面试题
护理自我鉴定范文
2013/10/06 职场文书
周鸿祎:教你写创业计划书
2013/12/30 职场文书
个人作风剖析材料
2014/02/02 职场文书
业务员简历自我评价
2014/03/06 职场文书
幸福家庭标语
2014/06/27 职场文书
自愿离婚协议书2015
2015/01/26 职场文书
个人年终总结开头
2015/03/06 职场文书
人间正道是沧桑观后感
2015/06/15 职场文书
Ubuntu18.04下QT开发Android无法连接设备问题解决实现
2022/06/01 Java/Android