问题背景:
在表格翻页组件中,有一个跳页输入框,当输入不合法字符时,利用绑定的指令去除不合法字符。
但是v-model不生效,在此记录一下,给前端的小伙伴们踩踩坑。
问题描述:
输入不合法字符时,期望输入框内的值和绑定的变量都回填之前的数字。例如输入‘?’,期望输入框和变量都显示‘1’;实际输入框显示‘1,变量显示‘1?’,v-model未生效。
<input type="text" v-pager-formatter="{ pagerFormatterMax: totalPage || 1 }" v-model="index" @blur="setPage()" @keyup.enter="$event.target.blur()" />
复制
v-pager-formatter就是输入框校验指令,当输入内容时,在指令中校验输入是否合法。
export default { updated(el: HTMLInputElement, binding: DirectiveBinding): void { const Service: InputValidator = new InputValidator(); // 最大页数 const totalPageNumber: number = binding.value.pagerFormatterMax; // 输入框值 let targetValue: string; const inputChange = (elRef): boolean => { // 校验是否合法,不合法替换不合法字符,返回合法字符 const limitNumber: string = Service.limitNumber(targetValue, 'int', 1, totalPageNumber); if (limitNumber !== targetValue) { // 如果有不合法字符,则回填合法字符 if (limitNumber) { elRef.value = limitNumber; } else { elRef.value = ''; } } return true; }; el.oninput = (event: Event): void => { targetValue = event.target['value']; inputChange(el); }; }, };
复制
在指令中,elRef.value = limitNumber后,v-model绑定的变量并不会更新。
问题原因:
v-model双向绑定原理实际上就是 "@input" 事件与 ":value" 属性的结合体。v-model未生效其实(:value绑定的变量未更新)其实就是在指令中改变输入框value时未触发“@input”事件,导致v-moel未生效。
解决方法:
手动触发input事件,使绑定的变量更新。EventTarget.dispatchEvent()方法会向一个指定的事件目标派发一个Event,并以合适的顺序(同步地)调用所有受影响的EventListener。
代码中加入elRef.dispatchEvent(new Event('input'))触发input事件,使v-model更新。这样就能解决这个问题。
export default { updated(el: HTMLInputElement, binding: DirectiveBinding): void { const Service: InputValidator = new InputValidator(); // 最大页数 const totalPageNumber: number = binding.value.pagerFormatterMax; // 输入框值 let targetValue: string; const inputChange = (elRef): boolean => { // 校验是否合法,不合法替换不合法字符,返回合法字符 const limitNumber: string = Service.limitNumber(targetValue, 'int', 1, totalPageNumber); if (limitNumber !== targetValue) { // 如果有不合法字符,则回填合法字符 if (limitNumber) { elRef.value = limitNumber; } else { elRef.value = ''; } elRef.dispatchEvent(new Event('input')); } return true; }; el.oninput = (event: Event): void => { targetValue = event.target['value']; inputChange(el); }; }, };
复制