Vue JS输入框正则限制下Backspace键失效与负号重复输入问题
问题解决方法
问题根因
原内联onkeydown逻辑存在3个核心缺陷:
- 正则
/^-?\d*\.?\d{0}$/限制小数点后只能有0位数字,只要输入小数位后,当前值就无法匹配正则,所有按键包括退格都会被拦截,直接导致退格失效 - 负号校验只判断当前值格式,没有限制负号只能在首位输入,也没有去重判断,所以可以输入多个负号
- 没有对退格、方向键等功能键做放行逻辑,所有按键都要过正则校验,功能键被错误拦截
修复方案
把内联的onkeydown替换为Vue事件绑定,单独写校验方法,逻辑更易维护:
修正后模板代码
<vs-input :value="contract.value" :class="isMobileOnly ? 'w-full' : 'w-1/2'" class="mx-auto" type="text" inputmode="decimal" :id="`value-${index}`" @keydown="handleValueKeydown($event, index)" :placeholder="contract.value === 0 ? undefined : 'Value'" @change="changeValue(index)" />
注:这里把type改为text避免浏览器原生number输入框的默认行为干扰自定义校验,加
inputmode="decimal"属性可以在移动端唤起数字键盘
校验方法代码(放到methods中)
methods: { handleValueKeydown(e, index) { // 放行功能键、系统组合键 const allowedKeys = ['Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Tab', '.'] if (allowedKeys.includes(e.key) || e.ctrlKey || e.metaKey) { return true } // 禁止输入e等非数字、非负号的字符 if (isNaN(Number(e.key)) && e.key !== '-') { e.preventDefault() return false } const inputEl = e.target const currentValue = inputEl.value // 负号校验:仅允许在首位输入1个负号 if (e.key === '-') { if (inputEl.selectionStart !== 0 || currentValue.includes('-')) { e.preventDefault() return false } return true } // 输入值格式校验,此处正则支持负号开头、最多1个小数点、小数点后最多2位,可按需调整 const newValue = currentValue.slice(0, inputEl.selectionStart) + e.key + currentValue.slice(inputEl.selectionEnd) const reg = /^-?\d*\.?\d{0,2}$/ if (!reg.test(newValue)) { e.preventDefault() return false } }, // 原有changeValue方法逻辑保持不变即可 changeValue(index) { // 原有逻辑保留 } }
验证效果
- 仅可以在输入内容最开头输入1个负号,其他位置输入负号会被自动拦截
- 退格、方向键等功能键可以正常使用,不受输入内容格式影响
- 正则可灵活调整:如果不需要小数,直接把正则改为
/^-?\d*$/即可
内容的提问来源于stack exchange,提问作者Abdullah Ch
相关产品推荐
相关产品推荐

