vue 表单验证插件demo

吐槽一下,现在找个前端工作怎么这么难啊!!
官方推荐插件的写法:
https://cn.vuejs.org/v2/guide/plugins.html
写法:
MyPlugin.install = function (Vue, options) { } 使用指令 directive完成插件;
使用:
Vue.use(MyPlugin)

对于表单验证插件哪些需求(目前实现):
默认的验证信息;
自定义验证规则与提示文本;
报错时机可选;
按顺序报错;

代码:myValidate.js

    //用来剔除重复的规则,以及规则的覆盖。默认后面的取代前面
    Array.prototype.uConcat = function (arr) {
        var comb = this.concat(arr)
            , unique = {}
            , result = []
    
        for (var i = 0; i < comb.length; i++) {
            // console.log(i, comb[i])
            var type = comb[i].type
            if (unique[type]) {
                var index = unique[type].index
                unique[type] = comb[i]
                unique[type].index = index;
            } else {
                unique[type] = comb[i]
                unique[type].index = i;
            }
        }
    
        for (var i = 0; i < 100; i++) {
            for (var item in unique) {
                if (unique[item].index === i) {
                    delete unique[item].index
                    result.push(unique[item])
                }
            }
        }
        return result
    }
    var regList = {
        ImgCode: /^[0-9a-zA-Z]{4}$/,
        SmsCode: /^\d{4}$/,
        MailCode: /^\d{4}$/,
        UserName: /^[\w|\d]{4,16}$/,
        Password: /^[\w!@#$%^&*.]{6,16}$/,
        Mobile: /^1[3|5|8]\d{9}$/,
        RealName: /^[\u4e00-\u9fa5 ]{2,10}$/,
        BankNum: /^\d{10,19}$/,
        Money: /^([1-9]\d*|0)$/,
        Answer: /^\S+$/,
        Email: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/
    }
    
    var cfg = {
        //非空
        nonvoid: (v, bool) => {
            if (bool) {
                return v.trim() ? 0 : ['nonvoid'];
            } else {
                return 0;
            }
        },
        reg: (v, reg) => reg.test(v) ? 0 : ['reg'],                //正则
        limit: (v, interval) => (+v >= interval[0] && +v <= interval[1]) ? 0 : ['limit', interval],
        equal: (v, target) => {                                                        //和什么相等
            var _list = document.getElementsByName(target), _target
            for (var i = 0; i < _list.length; i++) {
                if (_list[i].className.indexOf('va') > -1) {
                    _target = _list[i];
                }
            }
            console.log(target);
            return (_target.value === v) ? 0 : ['equal', _target.getAttribute('tag')]
        },
        unique: (v) => {
            var _list = document.getElementsByClassName('unique'),
                valList = [].map.call(_list, item => item.value)
            return (unique(valList).length === valList.length) ? 0 : ['unique']
        }
    };
    function check(v, conditions) {
        // 默认为0  false
        var res = 0;
        for (var i = 0; i < conditions.length; i++) {
            var condi = conditions[i],
                type = condi.type,
                typeVal = condi.typeVal;
            res = cfg[type](v, typeVal);
            //如果有自定义报错信息, 返回自定义的报错信息
            if (res) {
                res = condi.errMsg || res;
                break
            }
        }
        if(res){
            showErrMsg(conditions[0].tag,res);
        }
        return res;
    }
    function showErrMsg(name, checkResult) {
        if(typeof checkResult === 'string'){
            alert(checkResult);
        }else{
            var type = checkResult[0];
            var ext = checkResult[1] || [];
            var ERR_MSG = {
                nonvoid: `${name}不能为空`,
                reg: `${name}格式错误`,
                limit: `${name}必须在${ext[0]}与${ext[1]}之间`,
                equal: `两次${ext}不相同`,
                unique: `${name}重复`
            };
            alert(ERR_MSG[type]);
        }
    }
    
    function VaConfig(type, typeVal, errMsg, name, tag) {
        this.type = type;
        this.typeVal = typeVal;
        this.errMsg = errMsg;
        this.name = name;
        this.tag = tag;
    }
    var myValidate = {};
    myValidate.install = function (Vue, options) {
        // 1. 添加全局方法或属性
        Vue.myGlobalMethod = {};
        // 2. 添加全局资源
        Vue.directive('va', {
            bind: function (el, binding, vnode) {
                var vm = vnode.context;
                var name = binding.arg;
                var option = binding.modifiers;
                var tag = el.getAttribute('tag') || name;  // 用于显示错误信息  比如密码,账号
                var errMsg = el.getAttribute('errMsg') || '';  // 保存自定义显示错误
                var cfg = [];       //binding.arg  ,默认
                var optionCfg = []; // bingding.modifiers
                var customCfg = []; // 用户自定义规则,binding.value
                var configEnd = [];
                vm.configEnd || (vm.configEnd = {});
                el.className = 'va' + vm._uid;     // _uidd vue扩展实例,会有_uid属性 ,  vue.extend方法 扩展vue实例
                if(option.vanow){
                    el.addEventListener('change', function () {
                        var value = el.value;
                        //如果允许为空的此时为空,不校验
                        if (value === '' && option.canNull) {
                            return
                        }
                        check(value, vm.configEnd[name]);
                    });
                }
    
                var  createConfig = (type,ruleValue)=>{
                    return new VaConfig(type,ruleValue,errMsg,name,tag)
                }
                //默认非空,如果加了canNull的修饰符就允许为空
                if (!option.canNull) {
                    var NON_VOID = createConfig('nonvoid', true);
                    // 添加到基础验证规则,因为只有在非空的情况下验证才进行其他验证
                    cfg.push(NON_VOID);
                }
                // type 是否是在正则里面
                if (regList[name]) {
                    optionCfg.push(createConfig('reg',regList[name]));
                }
                // 如果修饰里面 有reg 的,添加到optionCfg
                var regOptions = Object.keys(option);
                for(var v of regOptions){
                    if(regList[v]){
                        optionCfg.push(createConfig('reg',regList[v]));
                    }
                }
                //用户自定义的规则   binding.value   [{minLength:6},{maxLength:8}]
                if (binding.value) {
                    customCfg = binding.value.map(item => {
                        let type = Object.keys(item)[0];
                        console.log(item[type])
                        return createConfig(type, item[type])
                    })
                }
                vm.configEnd[name] || (vm.configEnd[name] = [])
                vm.configEnd[name] = cfg.uConcat(optionCfg).uConcat(customCfg);
            }
    
        });
        Vue.directive('va-check',{
            bind:function (el,binding,vnode) {
                var vm = vnode.context;
                el.addEventListener('click',function () {
                    var domList = document.getElementsByClassName('va' + vm._uid);
                    vm.vaResult || (vm.vaResult = {})
                    for (var i = 0; i < domList.length; i++) {
                        var dom = domList[i],
                            name = dom.name,
                            value = dom.value,
                            conditions = vm.configEnd[name]
                        console.log(conditions)
                        var _result = check(value, conditions)
                        //如果返回不为0,则有报错
                        if (_result) {
                            //如果返回的是字符串,则为自定义报错; 如果是数组,则使用showErr 报错
                            return
                        }
                    }
                    //校验通过的回调
                    vm.$vaSubmit && vm.$vaSubmit()
                })
            }
        })
    
    };
    export default myValidate

代码:va.vue


        

使用方法

在main.js中:
import va from './myValidate.js';
Vue.use(va);
本插件使用了两个指令va与va-check,va使用在输入框失去焦点的情况 ;va-check使用在点击提交的情况下,验证所有的输入框;
showErrMsg中使用需要调用的显示提示信息的方法,可以将vm传入,使用vm.$alert,然后在methods中挂载$alert()方法,实现自定义;
vm.$vaSubmit 为自定义的通过验证之后的回调方法;
在指令directive中的binding参数中arg,modifiers,value来决定添加的验证规则;

你可能感兴趣的:(vue 表单验证插件demo)