vue 自写验证 加 jsx
Posted smallteeth
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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‘, width: ‘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 }
以上是关于vue 自写验证 加 jsx的主要内容,如果未能解决你的问题,请参考以下文章