vue3自订位数输出命令
日常生活的合作开发操作过程中可能将须要管制使用者输出的文本,比如说根本无法输出位数和小数,又或是是位数加-之类市场需求,不必专业术语间接上标识符。
import { Directive, ref, DirectiveBinding, Ref, unref, App, nextTick } fromvue;import { ElMessage } fromelement-plusimport { debounce } fromlodash;exporttypeObj={maxLength?: numberreg?: RegExp}letobj: Ref=ref({})constinputValue=ref()letreg: RegExpany=/[^\d]/g//警示提示exportfunctionwarnMsg(msgInfo: string, arg?: any){ElMessage({type:warning,showClose: true,dangerouslyUseHTMLString: true,message: msgInfo,…arg })}exportfunctionparseJson(jsonStr: string){returnJSON.parse(jsonStr,(k, v)=>{try {//将二阶数组转成二阶第一类if (eval(v) instanceofRegExp){returneval(v);} } catch (e){// nothing }returnv;});}/*** json第一类转json数组* @param { Object } json json第一类*/exportfunctionstringifyJson(json:{ [key: string]: any }){returnJSON.stringify(json,(k, v)=>{//将二阶第一类切换为二阶数组if (vinstanceofRegExp){returnv.toString();}returnv;});}functiontip(){if (reg.test(inputValue.value)){warnMsg(请输出位数!)}}//发放自订该事件consttrigger=(el: HTMLElement, type: any)=>{conste=document.createEvent(HTMLEvents);e.initEvent(type, true, true);el.dispatchEvent(e);}exportconstonlyNumber: Directive={mounted(el: any, binding: DirectiveBinding, vnode: any){constinput=el?.children[];if (binding.arg){try {obj.value=parseJson(binding.arg)if (unref(obj).maxLength){input.maxLength=unref(obj)?.maxLength }if (unref(obj).reg){reg=unref(obj)?.reg }} catch (error){ }}if (binding.value){reg=binding.value;}input.oninput=function (e: any){inputValue.value=this.value;this.value=this.value.replace(reg,);if (unref(obj).maxLength){if (this.value.length===unref(obj).maxLength){warnMsg(最小输出${unref(obj).maxLength}个字符)} }//问题标识符—> input 改为 update:modelValueif (vnode.dirs.length){vnode.dirs[].instance.$emit(input, this.value)} };input.addEventListener(input, debounce(tip,500))},beforeUnmount(el: any, binding: any, vnode: any){constinput=el;input.removeEventListener(input, tip)}}exportdefault {install(app: App){app.directive(onlyNumber, onlyNumber)}}
正如上面标识符所示原理很简单通过element-plus的输出框拿到dom,监听input该事件,拿到输出的值之后,通过二阶进行替换。所有的事情都已经准备完全了,我以为万事俱备了,正当我使用这个命令进行二次封装number输出框的时候,问题就出现了,在vue3中不能通过$emit来触发双向数据绑定。下面是我封装的number组件。
import { ref, computed, useSlots, PropType } fromvueexporttypeArg={maxLength?: numberreg?: RegExp}constprops=defineProps({modelValue:{type: String,default:},argOptions:{type: ObjectasPropType,default:()=>{// maxLength:5,// reg:/[^\d\,]/g }}})constemit=defineEmits([update:modelValue])constarg=stringifyJson(props.argOptions)constslots=useSlots()constval=computed({get(){returnprops.modelValue },set(v){emit(update:modelValue, v)}})/*** json第一类转json数组* @param { Object } json json第一类*/functionstringifyJson(json:{ [key: string]: any }){returnJSON.stringify(json,(k, v)=>{//将二阶第一类切换为二阶数组if (vinstanceofRegExp){returnv.toString();}returnv;});}
讲了这么多专业术语,到底会出现什么问题呢?
当我们正常输出值的时候如果不是二阶匹配的数据就会被替换为空,当输出最后一个值的时候并不会替换为空虽然输出内没有显示,但值已经是为非二阶匹配的值了,这不是我们想要的。

如何解决这个问题呢
正常的解决方法就是实现element-plus中输出框的数据双向绑定,我想到通过自订命令中的vnode拿到这个实例的$emit进行触发input该事件,在vue2中这是可行的,在vue3中并不能通过$emit(input,this.value)来触发可以通过$emits(“update:modelValue”,this.value)来触发如图2如果不了解这个update:modelValue的朋友如图三
暂时就根本无法想到这么多了。
总结
世上无难事,只要肯放弃就一定能解决问题。