• vue 自写验证 加 jsx


    import vTips from './component.js'
    
    var va = {};
    
    function unique(arr){
        var hashTable = {}, newArr = [];
        for(var i = 0;i < arr.length;i++){
            if(!hashTable[arr[i]]){
                hashTable[arr[i]] = true;
                newArr.push(arr[i]);
            }
        }
        return newArr;
    }
    
    function addClass(dom, _class){
        var hasClass = !!dom.className.match(new RegExp('(\s|^)' + _class + '(\s|$)'))
        if(!hasClass){
            dom.className += ' ' + _class
        }
    }
    
    //校验函数
    function check(v, conditions){
        var res = 0;                                        //0代表OK, 若为数组代表是某个字段的错误
        //验证函数
        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)=> {  return (v.length >= interval[0] && v.length <= 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];
                    }
                }
                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']
            }
        }
        for(var i = 0;i < conditions.length;i++){
            var condi = conditions[i],
                type = condi.type,
                typeVal = condi.typeVal
            res = cfg[type](v, typeVal)
            // console.log(res, v, type,typeVal)
            //如果有自定义报错信息, 返回自定义的报错信息
            if(res){
                res = condi.errMsg || res
                break
            }
        }
    
        return res;
    }
    
    function showErr(name, checkResult){
        var type = checkResult[0],
                ext = checkResult[1] || []
    
        var ERR_MSG = {
            nonvoid: `${name}不能为空`,
            reg: `${name}格式错误`,
            limit: `${name}必须在${ext[0]}与${ext[1]}之间`,
            equal: `两次${ext}不相同`,
            unique: `${name}重复`
        }
        //使用layer来报错,如果需要自定义报错方式,要把全文的layer集中起来包一层。
        return ERR_MSG[type];
    }
    
    
    /**
     * [VaConfig va配置的构造函数]
     * @param {[string]} type    [校验类型,如reg, limit等等]
     * @param {[*]} typeVal             [根据校验类型配置的值]
     * @param {[string]} errMsg  [报错信息]
     * @param {[string]} name    [用以ajax的字段名]
     * @param {[string]} tag     [中文名,用以报错]
     */
    function VaConfig(type, typeVal, errMsg, name, tag){
        this.type = type, this.typeVal = typeVal, this.errMsg = errMsg, this.name = name, this.tag = tag
    }
    
    //用来剔除重复的规则,以及规则的覆盖。默认后面的取代前面
    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
    }
    
    import regList from './reg.js';
    
    va.install = function(Vue, options){
        var tipError = vTips(Vue, {errorClass:'air-fromate-error'})
        Vue.directive('va',{
            bind:function(el, binding, vnode){
                var dom = el.querySelector('input')
                var vm = vnode.context
                    ,name = binding.arg === 'EXTEND' ? dom.getAttribute('name') : binding.arg
                    ,tag = dom.getAttribute('tag') || binding.value.tag
                    ,baseCfg = []                                        //默认的校验规则                         --不用写,默认存在的规则(如非空)
                    ,optionalConfig = []                                //用户选择的配置成套         --与name相关
                    ,customConfig = []                                    //用户自定义的规则(组件中) --bingding.value
                    ,option = binding.modifiers
                    ,regMsg = dom.getAttribute('regMsg') || binding.value.regMsg
                var eazyNew = (type, typeVal) =>{return new VaConfig(type, typeVal, '', name, tag)}
                var regNew = (typeVal) =>{return new VaConfig('reg', typeVal, regMsg, name, tag)}    //正则的新建
                var newClassName = 'va' + vm._uid
                addClass(dom,newClassName)
                dom.name = name
                vm.vaConfig || (vm.vaConfig = {})
                var NON_VOID = eazyNew('nonvoid', true)
    
                //默认非空,如果加了canNull的修饰符就允许为空
                if(!option.canNull){
                    baseCfg.push(NON_VOID)
                }
    
                //需要立即校验的框
                var oldValue='';
                Object.defineProperty(dom, '_value', {
                    configurable: true,
                    set: function(value) {
                        this.value = value;
                        if(oldValue!=value){
                            oninputCallback();                                               
                        }
                        oldValue = value;     
                    },
                    get: function() {
                        return this.value;
                    }
                });
                function oninputCallback(){
                    vm.vaResult || (vm.vaResult = {})
                    vm.vaVal || (vm.vaVal = {})
                    var value = dom.value,
                            conditions = vm.vaConfig[name],
                            para = dom.getAttribute('va-para')                //传给回调的参数
                    //如果允许为空的此时为空,不校验
                    if(value === '' && option.canNull){
                        vm.vaVal[name] = value
                        return
                    }               
                    vm.vaResult[name] = check(value, conditions);
                    var _result = vm.vaResult[name]
                    if(_result){
                        //如果返回的是字符串,则为自定义报错; 如果是数组,则使用showErr 报错
                        typeof _result === 'string' ? _result : _result=showErr(conditions[0].tag, _result);
                        dom.style.borderBottom = '1px solid  red'
                        dom.instance=tipError({el:dom,message:_result,target: dom.instance || null,})            
                        dom.value = vm.vaVal[name] = ''
                        return
                    }
                    tipError({el:dom,remove:true,target: dom.instance || null})
                    dom.style.borderBottom = '1px solid  rgba(0,0,0,0.04)'
                    vm.vaVal[name] = value
                    // vm.$vanow(para)                                     
                    
                    
                    // dom.addEventListener('oninput ', function(){
                    //     vm.vaResult || (vm.vaResult = {})
                    //     vm.vaVal || (vm.vaVal = {})
                    //     var value = dom.value,
                    //             conditions = vm.vaConfig[name],
                    //             para = dom.getAttribute('va-para')                //传给回调的参数
                    //     //如果允许为空的此时为空,不校验
                    //     if(value === '' && option.canNull){
                    //         vm.vaVal[name] = value
                    //         return
                    //     }               
                    //     vm.vaResult[name] = check(value, conditions);
                    //     var _result = vm.vaResult[name]
                    //     if(_result){
                    //         //如果返回的是字符串,则为自定义报错; 如果是数组,则使用showErr 报错
                    //         typeof _result === 'string' ? _result : _result=showErr(conditions[0].tag, _result);
                    //         dom.style.borderBottom = '1px solid  red'
                    //         dom.instance=tipError({el:dom,message:_result,target: dom.instance || null,})            
                    //         dom.value = vm.vaVal[name] = ''
                    //         return
                    //     }
                    //     tipError({el:dom,remove:true,target: dom.instance || null})
                    //     dom.style.borderBottom = '1px solid  rgba(0,0,0,0.04)'
                    //     vm.vaVal[name] = value
                    //     vm.$vanow(para)                    //写在实例内部method的回调
                    // })
                }
    
                //不能重复的
                if(option.unique){
                    optionalConfig.push(eazyNew('unique', name))
                }
    
                //如果有在正则表里
                var regOptions = Object.keys(option);
                for(var i = 0;i < regOptions.length;i++){
                    var regOption = regOptions[i]
                    if(regList[regOptions[i]]){
                        optionalConfig.push(regNew(regList[regOption]))
                    }
                }
    
                //如果regList里有name对应的,直接就加进optionalConfig
                if(regList[name]){
                    optionalConfig.push(regNew(regList[name]))
                }
    
                //用户自定义的规则
                if(binding.value.rol){
                    customConfig = binding.value.rol.map(item=>{
                        let type = Object.keys(item)[0];
                        if(type === 'reg'){
                            return regNew(item[type])
                        }else{
                            if(type === 'unique'){
                                addClass(dom, 'unique')
                            }
                            return eazyNew(type, item[type])
                        }
                    })
                }
    
                //规则由 默认规则 + 修饰符规则 + 写在属性的自定义规则 + 用户直接加到vm.vaConfig里的规则 合并(后面的同type规则会覆盖前面的)
                vm.vaConfig[name] || (vm.vaConfig[name] = [])
                vm.vaConfig[name] = baseCfg.uConcat(optionalConfig).uConcat(customConfig).uConcat(vm.vaConfig[name])
            },
        })
    
        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 = {})
                    vm.vaVal || (vm.vaVal = {})
                    var flag = true;
                    for(var i = 0;i < domList.length;i++){
                        var dom = domList[i],
                                name = dom.name,
                                value = dom.value,
                                conditions = vm.vaConfig[name]
                        var _result = check(value, conditions)                                 
                        //如果返回不为0,则有报错
                        if(_result){
                            //如果返回的是字符串,则为自定义报错; 如果是数组,则使用showErr 报错
                            typeof _result === 'string' ? _result : _result=showErr(conditions[0].tag, _result);
                            dom.instance=tipError({el:dom,message:_result,target: dom.instance || null,})
                            dom.style.borderBottom = '1px solid  red'
                            flag=false;
                        }else{
                            dom.style.borderBottom = '1px solid  rgba(0,0,0,0.04)'
                            tipError({el:dom,remove:true,target: dom.instance || null})
                        }
                        vm.vaVal[name] = value
                    }
                    //校验通过的回调
                    if(flag){
                        console.log(vm)
                        vm.$vaSubmit(vm.vaVal)                
                    }
                    // layer.msgWarn('全部校验成功')
                })
    
            }
        })
    
        Vue.directive('va-test',{
            bind: function(el, binding, vnode){
                var vm = vnode.context
                el.addEventListener('click', function(){
                    vm.vaResult || (vm.vaResult = {})
                    vm.vaVal || (vm.vaVal = {})
    
                    var dom = document.getElementsByName(binding.arg)[0],
                            name = dom.name,
                          value = dom.value,
                          conditions = vm.vaConfig[name]
    
                    var _result = check(value, conditions)
                    //如果返回不为0,则有报错
                    if(_result){
                        //如果返回的是字符串,则为自定义报错; 如果是数组,则使用showErr 报错
                        typeof _result === 'string' ? layer.msgWarn(_result) : showErr(conditions[0].tag, _result)
                        return
                    }
    
                    vm.vaVal[name] = value
                    var callback = Object.keys(binding.modifiers)[0]
                    vm[callback]()
                })
            }
        })
    
    
        /**
       **  在实例的monuted周期使用 api设置自定义配置
         */
        Vue.prototype.VaConfig = VaConfig
    }
    export default va;

    上面是验证 下面是jsx

    var component = {
        name: 'vTips',
        data () {
          return {
            exist: false
          }
        },
        props: {
          position: {
            type: Object,
            default: () => {
              return {
                top: 48,
                left: 0
              }
            }
          },
          message: {
            type: String,
            default: ''
          },
          errorClass: {
            type: String,
            default: 'air-form-err'
          },
          errorIcon: {
            type: String,
            default: ''
          }
        },
        render (h) {
          if (!this.exist) return
          return h('div', {
            style: {
              fontSize: '12px',
              color: '#F2553D',
              position: 'absolute',
              top:'48px',
              left: this.position.left + 'px',
              backgroundColor: '#fff',
              padding: '2px 8px',
            //   display:'none',
              margin: 0,
              zIndex: '99',
            //   boxShadow: '0 -4px 4px rgba(0,0,0,.12), 0 0 6px rgba(0,0,0,.04)',
              border: "1px solid rgba(0,0,0,0.12)",
              borderRadius: '4px'
            },
            class: [this.errorClass]
          }, [
            h('i', {
              class: [this.errorIcon]
            }),
            h('b', {
              style: {
                position: 'absolute',
                top: '-5px',
                bottom: '-5px',
                 '8px',
                height: '8px',
                display: 'block',
                borderLeft: '1px solid rgba(0,0,0,.1)',
                transform: 'rotateZ(45deg)',
                borderTop: '1px solid rgba(0,0,0,.1)',
                borderSizing: 'border-box',
                backgroundColor: '#fff'
              }
            }),
            h('span', this.message)
          ])
        }
      }
    
    
      
      export default function (Vue, config) {
        const PromptConstructor = Vue.extend(component)
        const tipsList = []
        
        function getAnInstance () {
          if (tipsList.length > 1) {
            const instance = tipsList[0]
            tipsList.splice(0, 1)
            return instance
          }
          return new PromptConstructor({
            el: document.createElement('div')
          })
        }
      
        const returnAnInstance = instance => {
          if (instance) {
            tipsList.push(instance)
          }
        }
      
        function getElPosition (el) {
          if (window.getComputedStyle && (el.parentNode && !el.parentNode.style.position)) {
            const _position = window.getComputedStyle(el.parentNode).position
            if (!_position || _position === 'static') {
              el.parentNode.style.position = 'relative'
            }
          }
          return {
            top: el.offsetTop - 38,
            left: el.offsetLeft
          }
        }
      
        const removeDom = target => {
          const container = getContainer()
          if (target.parentNode) {
            container.removeChild(target)
          }
        }
      
        PromptConstructor.prototype.close = function (el) {
          this.exist = false
          // removeDom(el)
          // this.exist = true
          // returnAnInstance(this)
        }
        
        const vTips = (options = {}) => {
          const instance = options.target || getAnInstance()
          const container = options.el.parentNode
          if (options.remove) {
            
            instance.close(options.target)
            return
          }
      
          instance.message = typeof options === 'string' ? options : options.message
          instance.position = options.el ? getElPosition(options.el, instance) : options.position
          instance.exist = false
          instance.errorClass = options.errorClass || config.errorClass
          instance.errorIcon = options.errorIcon || config.errorIcon
          container.appendChild(instance.$el)
          Vue.nextTick(function () {
            instance.exist = true
          })
          return instance
        }
      
        return vTips
      }
  • 相关阅读:
    ubuntu下eclipse打开win下的代码中文出现乱码
    ubuntu设置ip和dns
    堆和栈的区别
    分析与利用
    C语言ASM汇编内嵌语法
    vnc无法显示桌面
    草稿本(1)总结
    系统虚拟化:原理与实现
    错误
    ab(http)与abs(https)压测工具
  • 原文地址:https://www.cnblogs.com/smallteeth/p/8868288.html
Copyright © 2020-2023  润新知