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实现tab键进行选择后enter键触发click行为
Mar 29 jQuery
jQuery源码解读之extend()与工具方法、实例方法详解
Mar 30 jQuery
jquery.uploadifive插件怎么解决上传限制图片或文件大小问题
May 08 jQuery
jQuery.form.js的使用详解
Jun 14 jQuery
jQuery常见面试题之DOM操作详析
Jul 05 jQuery
使用 jQuery 实现表单验证功能
Jul 05 jQuery
jquery在vue脚手架中的使用方式示例
Aug 29 jQuery
jQuery.Sumoselect插件实现下拉复选框效果
Nov 09 jQuery
基于jquery的on和click的区别详解
Jan 15 jQuery
jQuery实现的点击按钮改变样式功能示例
Jul 21 jQuery
jQuery ajax仿Google自动提示SearchSuggess功能示例
Mar 28 jQuery
jquery 键盘事件 keypress() keydown() keyup()用法总结
Oct 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
PHP使用preg_split()分割特殊字符(元字符等)的方法分析
2017/02/04 PHP
phpStudy vscode 搭建debug调试的教程详解
2020/07/28 PHP
javascript 定义初始化数组函数
2009/09/07 Javascript
javascript常用方法、属性集合及NodeList 和 HTMLCollection 的浏览器差异
2010/12/25 Javascript
javascript实现div浮动在网页最顶上并带关闭按钮效果实例
2013/08/13 Javascript
jQuery 追加元素的方法如append、prepend、before
2014/01/16 Javascript
angularJS 入门基础
2015/02/09 Javascript
全面解析Bootstrap中scrollspy(滚动监听)的使用方法
2016/06/06 Javascript
全面解析Bootstrap中tooltip、popover的使用方法
2016/06/13 Javascript
Angular2 Service实现简单音乐播放器服务
2017/02/24 Javascript
js仿淘宝评价评分功能
2017/02/28 Javascript
jQuery自定义元素右键点击事件(实现案例)
2017/04/28 jQuery
Vue之Watcher源码解析(1)
2017/07/19 Javascript
简单实现js进度条加载效果
2020/03/25 Javascript
详解vantUI框架在vue项目中的应用踩坑
2018/12/06 Javascript
详解jQuery如何实现模糊搜索
2019/05/10 jQuery
jQuery实现倒计时功能完整示例
2020/06/01 jQuery
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
[01:25]DOTA2超级联赛专访iG 将调整状态找回自己
2013/06/05 DOTA
在Python中使用异步Socket编程性能测试
2014/06/25 Python
Python中unittest用法实例
2014/09/25 Python
python实现从web抓取文档的方法
2014/09/26 Python
Django实现简单分页功能的方法详解
2017/12/05 Python
Python实现生成随机日期字符串的方法示例
2017/12/25 Python
python中不能连接超时的问题及解决方法
2018/06/10 Python
python 利用for循环 保存多个图像或者文件的实例
2018/11/09 Python
python创建属于自己的单词词库 便于背单词
2019/07/30 Python
Python sklearn库实现PCA教程(以鸢尾花分类为例)
2020/02/24 Python
django 数据库 get_or_create函数返回值是tuple的问题
2020/05/15 Python
东南亚排名第一的服务市场:kaodim
2019/03/28 全球购物
会计专业毕业生推荐信
2013/11/05 职场文书
酒店仓管员岗位职责
2014/04/28 职场文书
真诚的求职信
2014/07/04 职场文书
高中国旗下的演讲稿
2014/08/28 职场文书
使用Python开发贪吃蛇游戏 SnakeGame
2022/04/30 Python
Nginx如何获取自定义请求header头和URL参数详解
2022/07/23 Servers