如何在文本输入框的输入事件中同时获取更新后的值并取消事件?
方案1:使用beforeinput事件(推荐,现代浏览器兼容)
beforeinput事件会在输入内容写入DOM之前触发,支持取消输入,同时可以直接获取插入位置、待输入内容,自行拼接得到输入后的完整值:
<input type="text" id="validateInput">
const input = document.querySelector('#validateInput') input.addEventListener('beforeinput', e => { // 原有值 const oldVal = input.value // 内容插入/替换的起始、结束位置 const start = input.selectionStart const end = input.selectionEnd // 待插入的新内容,删除操作时值为null const newChar = e.data ?? '' // 拼接得到输入完成后的完整值 const newVal = oldVal.slice(0, start) + newChar + oldVal.slice(end) // 你的自定义校验逻辑,示例:不允许输入数字、总长度不超过10 const isValid = /^[^0-9]*$/.test(newVal) && newVal.length <= 10 if (!isValid) { // 校验不通过直接取消输入 e.preventDefault() } })
该方案支持所有输入场景:键盘输入、粘贴、拖拽插入内容、输入法输入都能正常触发,性能开销极低。Chrome 60+、Firefox 87+、Safari 10.1+均原生支持。
方案2:兼容旧浏览器的回滚方案
如果需要兼容IE等老旧浏览器,可以通过缓存合法值+输入后校验回滚的方式实现:
const input = document.querySelector('#validateInput') // 缓存上一次校验通过的值和光标位置 let lastValidVal = input.value let lastStart = input.selectionStart let lastEnd = input.selectionEnd // 输入前缓存当前状态 input.addEventListener('keydown', () => { lastValidVal = input.value lastStart = input.selectionStart lastEnd = input.selectionEnd }) // 输入后校验,不通过直接回滚 input.addEventListener('input', () => { const currentVal = input.value // 你的自定义校验逻辑 const isValid = /^[^0-9]*$/.test(currentVal) && currentVal.length <= 10 if (!isValid) { input.value = lastValidVal // 恢复光标位置,避免光标自动跳到末尾 input.setSelectionRange(lastStart, lastEnd) return } // 校验通过更新缓存 lastValidVal = currentVal })
该方案兼容全版本浏览器,缺点是校验不通过时会有极短的内容闪变,大部分场景下用户无感知。
内容的提问来源于stack exchange,提问作者Jannik
相关产品推荐
相关产品推荐

