手写一个表单验证封装类

Github地址:表单校验类

关于该类

支持的校验规则

  1. 非空判断(required)
  2. 手机号校验(phone)
  3. 邮箱校验(email)
  4. 数字类型校验(number)
  5. 数字范围校验(numberRange)
  6. 自定义校验函数(customize)

内置的校验函数

  1. testRequired
  2. testPhone
  3. testEmail
  4. testNumber
  5. testNumberRange

直接调用内置函数时,返回如下格式类型的结果:

{
	res: boolean,
	msg: string
}

初始化构造函数

在初始化构造函数时传入校验规则(具体格式参考下面的使用示例)。最后会返回校验出的第一个错误信息,如果全部校验成功则返回空字符串。

特别说明

  1. 该类对所有类型的校验都初始化了错误信息,当用户不填错误信息时,将自动使用默认信息。校验规则与默认信息的对应关系如下:
 {
  	 'required': '该项必填',
     'phone': '手机号不合法',
     'email': '邮箱不合法',
     'number': '所填项必须为有效数字',
     'numberRange': '数字必须在正确的范围内',
     'customize': '对于自定义校验函数,请输入自定义的错误信息'
 }
  1. 对于自定义校验函数,请返回一个布尔值
  2. 当校验规则只有一个或错误信息只有一个时,也可以直接传入一个字符串

使用示例

该类有两种使用方法,第一种是构造函数中什么都不传,然后直接调用类的公有方法进行判断。

第二种是在初始化构造函数时传入校验规则。请按照下面示例中的格式填写,注意value必填,rules必填。

然后调用res函数,该函数返回一个Promise。在链式调用中,如果err为空则校验成功,否则会返回第一条失败信息。

const Validate = require('./validate');

let phone = '17157527818';
let number = '0';
let email = '[email protected]'
let customize = '12';

const validation = new Validate();
const res = validation.testPhone(phone);
console.log(res);

const validate = new Validate([
    {
        value: phone,
        rules: ['required', 'phone'],
        msgs: ['手机号不能为空', '手机号错误']
    }
    , {
        value: number,
        rules: ['required', { type: 'number', max: 50, min: 1 }],
        msgs: ['数字不能为空', '']
    }
    , {
        value: email,
        rules: 'email'
    }, {
        value: customize,
        rules: (value) => value.startsWith('0'),
        msgs: '该项必须以0开头'
    }
]);

validate.res().then((err) => {
    if (!err) console.log('成功');
    else console.log('失败', err);
})

打印出结果:

{ res: true, msg: 'success' }
失败 该项必须在1~50范围内

表单校验类全部代码

最后附上完整代码

const _errors = Symbol();
const _initValidate = Symbol();
const _validateRule = Symbol();
const _ruleMsg = Symbol();
const _initMsgs = Symbol();
const _handleRes = Symbol();
const _toArray = Symbol();

class Validate {
    constructor(args) {
        // 错误数组
        this[_errors] = [];
        // 规则与错误信息的映射
        this[_ruleMsg] = {
            'required': '该项必填',
            'phone': '手机号不合法',
            'email': '邮箱不合法',
            'number': '所填项必须为有效数字',
            'numberRange': '数字必须在正确的范围内',
            'customize': '对于自定义校验函数,请输入自定义的错误信息'
        }
        if (args) {
            args = this[_toArray](args);
            args.forEach(item => {
                // 初始化每一条规则
                this[_initValidate](item);
                // 校验每一条规则,当遇到错误时,结束其他的校验
                if (!this[_validateRule](item)) {
                    return;
                }
            })
        }
    }

    /**
    * 判空及初始化错误信息
    *
    * @param {object} item
    * @memberof Validate
    */
    [_initValidate](item) {
        // console.log("初始化校验规则中……", item);
        let { value = '', rules = [], msgs = [] } = item;
        // 判空
        if (value === undefined) {
            throw Error('当前没有要校验的值,请确保初始化构造函数时value不为空!');
        }
        if (!rules || rules.length === 0) {
            throw Error('请添加校验规则');
        } else if (rules) {
            rules = this[_toArray](rules);
            rules.forEach(rule => {
                if (!rule) {
                    throw Error('校验规则不能为空!');
                }
            })
        }
        msgs = this[_toArray](msgs);
        // 初始化msgs
        item.msgs = this[_initMsgs](msgs, rules);
    }

    /**
     * 开始校验,当出现一个错误时停止剩下的校验
     *
     * @param {object} item
     * @memberof Validate
     */
    [_validateRule](item) {
        let { value, rules, msgs } = item;
        rules = this[_toArray](rules);
        msgs = this[_toArray](msgs);
        rules.forEach((rule, index) => {
            const curMsg = msgs[index];
            if (typeof rule === 'string') {
                // 使用内置校验规则
                // 拼接函数名称
                let funSuffix = rule[0].toUpperCase() + rule.substring(1);
                // 函数执行结果
                let res = this[`test${funSuffix}`](value, curMsg).res;
                // 遇到一个错误即返回false
                if (!res) return false;
            } else if (rule.toString() === '[object Object]') {
                // 内置校验规则,遇到多项规则叠加
                if (rule.type === 'number') {
                    let res = this.testNumberRange(value, curMsg, rule).res;
                    if (!res) return false;
                }
            } else if (typeof rule === 'function') {
                // 自定义校验规则
                let res = this[_handleRes](rule(value), 'customize', curMsg).res;
                if (!res) return false;
            }
        })

    }

    /**
     * 初始化错误信息,将用户没有定义的值赋为初始值
     *
     * @param {*} msgs
     * @param {*} rules
     * @returns
     * @memberof Validate
     */
    [_initMsgs](msgs, rules) {
        // 将msgs长度与rules长度对齐,不够的补为空字符串
        if (msgs.length < rules.length) {
            rules.forEach((rule, index) => {
                if (msgs[index] === undefined) msgs[index] = '';
            })
        }
        let res = msgs;

        // 判断msgs每一项是否为空,将为空的项赋值为初始值
        msgs.forEach((msg, index) => {
            if (!msg) {
                const rule = rules[index];
                if (typeof rule === 'string') {
                    if (!this[_ruleMsg][rule]) {
                        throw Error('该校验规则不存在')
                    } else {
                        res[index] = this[_ruleMsg][rule];
                    }
                }
            }
        })
        return res;
    }

    /**
     * 校验结果函数
     *
     * @returns {Promise}
     * @memberof Validate
     */
    res() {
        return new Promise((resolve, reject) => {
            if (this[_errors].length === 0) {
                resolve('');
            } else {
                // 校验失败,返回第一个错误
                resolve(this[_errors][0]);
            }
        })
    }

    /**
     * 手机号验证
     *
     * @param {*} value
     * @param {string} msg
     * @returns
     * @memberof Validate
     */
    testPhone(value, msg) {
        const phoneRexp = /^1[3456789]\d{9}$/;
        const res = phoneRexp.test(value);
        return this[_handleRes](res, 'phone', msg);
    }

    /**
     * 邮箱验证
     *
     * @param {*} value
     * @param {string} msg
     * @returns
     * @memberof Validate
     */
    testEmail(value, msg) {
        const emailRexp = /^([A-Za-z0-9_\-\.])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,4})$/;
        const res = emailRexp.test(value);
        return this[_handleRes](res, 'email', msg);
    }

    /**
     * 非空校验
     *
     * @param {*} value
     * @param {string} msg
     * @returns
     * @memberof Validate
     */
    testRequired(value, msg) {
        const res = value && value.length > 0;
        return this[_handleRes](res, 'required', msg);
    }


    /**
     *数字类型校验
     *
     * @param {*} value
     * @param {string} msg
     * @returns
     * @memberof Validate
     */
    testNumber(value, msg) {
        const numberRexp = /^[0-9]+$/;
        const res = numberRexp.test(value);
        return this[_handleRes](res, 'number', msg);
    }

    /**
     * 校验数字范围
     *
     * @param {*} value
     * @param {*} msg
     * @param {*} rule
     * @returns
     * @memberof Validate
     */
    testNumberRange(value, msg, rule) {
        const numberTest = this.testNumber(value, msg);
        // 非数字
        if (!numberTest.res) return numberTest;
        const { max, min } = rule;
        let res;
        if (!max && !min) return numberTest;
        else if (!max) {
            // 只定义了最小值
            res = Number(value) >= min;
            msg = msg || '该项必须大于' + min;
        } else if (!min) {
            // 只定义了最大值
            res = Number(value) <= max;
            msg = msg || '该项必须小于' + max;
        } else {
            // 最大值,最小值都有
            res = Number(value) >= min && Number(value) <= max;
            msg = msg || `该项必须在${min}~${max}范围内`;
        }
        return this[_handleRes](res, 'numberRange', msg)
    }

    /**
     *处理验证结果,返回统一的格式
     *
     * @param {boolean} judgeRes
     * @param {*} rule
     * @param {string} msg
     * @returns {res: boolean, msg: string}
     * @memberof Validate
     */
    [_handleRes](judgeRes, rule, msg) {
        if (!judgeRes) {
            // 校验失败
            let errorMsg = msg || this[_ruleMsg][rule] || '';
            this[_errors].push(errorMsg);
            return {
                res: false,
                msg: errorMsg
            }
        } else {
            // 校验成功
            return {
                res: true,
                msg: 'success'
            }
        }
    }

    /**
     * 将非数组转为数组
     *
     * @param {*} value
     * @returns
     * @memberof Validate
     */
    [_toArray](value) {
        return Array.isArray(value) ? value : [value];
    }
}

module.exports = Validate;

你可能感兴趣的:(JavaScript,js,javascript,es6)