Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

简单的表单验证 #33

Open
5Mi opened this issue Jun 24, 2016 · 1 comment
Open

简单的表单验证 #33

5Mi opened this issue Jun 24, 2016 · 1 comment

Comments

@5Mi
Copy link
Owner

5Mi commented Jun 24, 2016

  • class 类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。

贴一个内部写的简单验证js

import {$, isEmpty} from './tools'

/**
 * 表单验证方法
 */
export default class Valid {
    //需要加的属性,值为"false"或false时才无效
    static attr = {
        //必填
        required: "required",
        //最小长度
        minlength: "minlength",
        //正则匹配
        pattern: "pattern"
    };

    //正则匹配
    static regexps = {
        //url
        url: /^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$/,
        //邮箱
        email: /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+\.(?:com|cn)$/,
        //时分秒
        timeString: /^(2[0-3]|[01]?[0-9]):([0-5]?[0-9]):([0-5]?[0-9])$/,
        //日期
        dateString: /^(1[0-2]|0?[1-9])\/(3[01]|[12][0-9]|0?[1-9])\/(?:[0-9]{2})?[0-9]{2}$/,
        //手机号码
        mobile: /^1[3|4|5|7|8]\d{9}$/,
        //座机号码
        phone: /\d{3}-\d{8}|\d{4}-\d{7}/,
        //密码(字母开头,6-16字节,允许字母数字下划线)
        password: /^[a-zA-Z][a-zA-Z0-9_]{5,15}$/,
        //整数
        number: /^-?[0-9]\d*$/
    };
    //是否含有属性
    static hasAttr(dom, attr) {
        let str = dom.getAttribute(attr);
        return typeof str != "undefined" && str != "false" && str !== null;
    }

    //显示警告信息,symbol只是用来区分不同的警告信息显示隐藏
    static showWarn(text, dom, symbol) {
        let [offset,width,height] = [dom.getBoundingClientRect(), dom.offsetWidth, dom.offsetHeight];
        for (let item of [...$(`.warnMsg`)]) {
            if (item.getAttribute('class').indexOf(symbol) == -1) {
                document.body.removeChild(item);
            }
        }
        let class_old = dom.getAttribute("class");
        //没有class属性会返回null,需判断
        class_old = class_old ? class_old.replace(/(^\s*)|(\s*$)/g, '') : '';
        if (!isEmpty(class_old) && class_old.indexOf('error') != -1) {
            class_old = class_old.replace('error', '');
        }
        dom.setAttribute("class", `error ${class_old}`);
        var warnNode = document.createElement("span");
        warnNode.setAttribute("class", `warnMsg warnMsg-${symbol}`);
        warnNode.innerText = text;
        document.body.insertBefore(warnNode, document.body.firstChild);
        let warnHeight = warnNode.offsetHeight;
        warnNode.style.top = (offset.top + document.body.scrollTop - warnHeight) + "px";
        warnNode.style.left = (offset.left + width - warnNode.offsetWidth) + "px";
        warnNode.style.opacity = 1;
        document.body.scrollTop = offset.top + document.body.scrollTop - warnHeight;
        let timer = setTimeout(function () {
            clearTimeout(timer);
            for (let item of [...$(`.warnMsg-${symbol}`)]) {
                warnNode.style.opacity = 0;
                document.body.removeChild(warnNode);
                //dom.setAttribute("class",class_old);
                //dom.focus();
            }
        }, 2000);
    }

    //验证通过去掉错误样式
    static removeWarn(event) {
        let _this = event.target;
        let boo = Valid.validInput(_this);
        //_this.removeEventListener('input');
        if (boo) {
            let class_this = _this.getAttribute("class");
            class_this = class_this ? class_this.replace(/(^\s*)|(\s*$)/g, '') : '';
            if (!isEmpty(class_this) && class_this.indexOf('error') != -1) {
                class_this = class_this.replace('error', '');
            }
            _this.setAttribute("class", class_this);
        }
    }

    //必填
    static validRequired(text, dom) {
        let boo = isEmpty(dom.value);
        boo && Valid.showWarn(text, dom, "required");
        return boo;
    }

    //最小长度
    static validMinLength(text, min, dom) {
        let boo = dom.value.length < Number(min);
        boo && Valid.showWarn(text, dom, "minLength");
        return boo;
    }

    //正则
    static validPattern(text, reg, dom) {
        let value = dom.value;
        let regExp = new RegExp(reg);
        let boo = !regExp.test(value);
        boo ? Valid.showWarn(text, dom, "pattern") : null;
        return boo;
    }

    /**
     * 单个input校验,不通过返回false
     * @param dom
     * @returns {boolean}
     */
    static validInput(dom) {
        if (Valid.hasAttr(dom, Valid.attr.required)) {
            let boo = Valid.validRequired("必填", dom);
            if (boo) {
                return false;
            }
        }
        if (Valid.hasAttr(dom, Valid.attr.minlength)) {
            let minlength = dom.getAttribute(Valid.attr.minlength);
            let boo = Valid.validMinLength(`至少${minlength}位`, minlength, dom);
            if (boo) {
                return false;
            }
        }
        if (Valid.hasAttr(dom, Valid.attr.pattern)) {
            let reg = dom.getAttribute(Valid.attr.pattern);
            let boo = Valid.validPattern(`格式不匹配`, reg, dom);
            if (boo) {
                return false;
            }
        }
        if (dom.getAttribute("type") == "email") {
            let boo = Valid.validPattern(`必须为email地址`, Valid.regexps.email, dom);
            if (boo) {
                return false;
            }
        }
        if (dom.getAttribute("type") == "tel" && dom.getAttribute("mobile")) {
            let boo = Valid.validPattern(`必须为手机号码`, Valid.regexps.mobile, dom);
            if (boo) {
                return false;
            }
        }
        if (dom.getAttribute("type") == "tel" && dom.getAttribute("phone")) {
            let boo = Valid.validPattern(`必须为电话号码`, Valid.regexps.phone, dom);
            if (boo) {
                return false;
            }
        }
        if (dom.getAttribute("type") == "tel") {
            let boo = Valid.validPattern(`必须为电话号码`, Valid.regexps.mobile, dom) && Valid.validPattern(`必须为电话号码`, Valid.regexps.phone, dom);
            if (boo) {
                return false;
            }
        }
        if (dom.getAttribute("type") == "number") {
            let boo = Valid.validPattern(`必须为数字`, Valid.regexps.number, dom);
            if (boo) {
                return false;
            }
        }
        return true;
    }

    /**
     * 表单校验,不通过返回false
     * @param dom
     * @returns {Promise}
     */
    static validForm(dom) {
        let boo = true;
        let iptDom = dom.getElementsByTagName("input");
        let textDom = dom.getElementsByTagName("textarea");
        let selectDom = dom.getElementsByTagName("select");
        for (let item of [...iptDom, ...textDom]) {
            //添加事件监听   监听oninput  调用Valid.removeWarn方法
            item.addEventListener('input', Valid.removeWarn, false);
            boo = Valid.validInput(item);
            if (!boo) {
                break;
            }
        }
        //select验证, value小于0不通过(根据实际情况修改)
        if (boo) {
            for (let sel of [...selectDom]) {
                if (Valid.hasAttr(sel, Valid.attr.required)) {
                    sel.addEventListener('change', function (event) {
                        let _this = event.target;
                        let value = Number(_this.value);
                        if (value >= 0 || isNaN(value)) {
                            let class_this = _this.getAttribute("class");
                            if (!isEmpty(class_this) && class_this.indexOf('error') != -1) {
                                class_this = class_this.replace('error', '');
                            }
                            _this.setAttribute("class", class_this);
                        }
                    }, false);
                    let val = Number(sel.value);
                    boo = val >= 0 || isNaN(val);
                    if (!boo) {
                        Valid.showWarn("必选", sel, "select");
                        break;
                    }
                }
            }
        }
        return new Promise((resolve, reject) => {
            resolve(boo);
        });
    }
}
@5Mi
Copy link
Owner Author

5Mi commented Jun 2, 2020

/* eslint-disable eqeqeq */
/* eslint-disable no-redeclare */
/* eslint-disable default-case */
/**
 * var rule = [
    { name: "nickname", checkType: "string", checkRule: "1,3", errorMsg: "姓名应为1-3个字符" },
    { name: "gender", checkType: "in", checkRule: "男,女", errorMsg: "请选择性别" },
    { name: 'pw_confirm', checkType: 'same', checkRule: this.form.pw, errorMsg: '密码输入不一致' },
    // allowNull:true 为空时不校验,非空时校验checkType
    { name: 'mail', allowNull:true, checkType: 'email', errorMsg: '邮箱格式有误' }
    //......
];
 */
export default {
  error: '',
  check: function(data, rule) {
    for (var i = 0; i < rule.length; i++) {
      if (!rule[i].checkType) {
        return true
      }
      if (!rule[i].name) {
        return true
      }
      if (!rule[i].errorMsg) {
        return true
      }
      if (!data[rule[i].name]) {
        // 允许为空, 但非空时要check
        if (rule[i].allowNull) {
          continue
        } else {
          this.error = rule[i].errorMsg
          return false
        }
      }

      switch (rule[i].checkType) {
        case 'string':
          var reg = new RegExp('^.{' + rule[i].checkRule + '}$')
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'int':
          var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$')
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'between':
          if (!this.isNumber(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          var minMax = rule[i].checkRule.split(',')
          minMax[0] = Number(minMax[0])
          minMax[1] = Number(minMax[1])
          if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'betweenD':
          var reg = /^-?[1-9][0-9]?$/
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          var minMax = rule[i].checkRule.split(',')
          minMax[0] = Number(minMax[0])
          minMax[1] = Number(minMax[1])
          if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'betweenF':
          var reg = /^-?[0-9][0-9]?.+[0-9]+$/
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          var minMax = rule[i].checkRule.split(',')
          minMax[0] = Number(minMax[0])
          minMax[1] = Number(minMax[1])
          if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'same':
          if (data[rule[i].name] != rule[i].checkRule) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'notsame':
          if (data[rule[i].name] == rule[i].checkRule) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'email':
          var reg = /^\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'phoneno':
          var reg = /^1[0-9]{10,10}$/
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'zipcode':
          var reg = /^[0-9]{6}$/
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'reg':
          var reg = new RegExp(rule[i].checkRule)
          if (!reg.test(data[rule[i].name])) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'in':
          if (rule[i].checkRule.indexOf(data[rule[i].name]) == -1) {
            this.error = rule[i].errorMsg
            return false
          }
          break
        case 'notnull':
          if (data[rule[i].name] == null || data[rule[i].name].length < 1) {
            this.error = rule[i].errorMsg
            return false
          }
          break
      }
    }
    return true
  },
  isNumber: function(checkVal) {
    var reg = /^-?[1-9][0-9]?.?[0-9]*$/
    return reg.test(checkVal)
  }
}

使用

const rule = [
        { name: 'eventTitle', checkType: 'notnull', errorMsg: '事件主题不能为空' },
        { name: 'eventTitle', checkType: 'string', checkRule: '1,50', errorMsg: '事件主题不能超过50个字符' },
        { name: 'eventContent', checkType: 'notnull', errorMsg: '输入事件描述' },
        { name: 'eventContent', checkType: 'string', checkRule: '1,500', errorMsg: '事件描述不能超过500个字符' },
        { name: 'eventTypeId', checkType: 'notnull', errorMsg: '选择事件类型' },
        { name: 'eventScale', checkType: 'notnull', errorMsg: '选择事件规模' },
        { name: 'urgency', checkType: 'notnull', errorMsg: '选择紧急程度' },
        { name: 'eventAddress', checkType: 'notnull', errorMsg: '输入地址' },
        { name: 'eventAddress', checkType: 'string', checkRule: '1,50', errorMsg: '地址不能超过50个字符' }
        // { name: 'imageList', checkType: 'notnull', errorMsg: '上传事件照片或视频' }
      ]

const data = {
        eventTitle: this.eventTitle,
        eventContent: this.eventContent,
        eventTypeId: this.eventTypeSelectList[this.eventTypeSelectList.length - 1].eventId,
        eventScale: this.eventScale,
        urgency: this.urgency,
        eventAddress: this.eventAddress,
        imageList: this.imageList
      }
      // checker 
      if (!checker.check(data, rule)) {
        console.log(checker.error)
        return uni.showToast({
          icon: 'none',
          title: checker.error
        })
      }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant