优先用 beforeinput 拦截非法字符,它在插入前触发且可 preventdefault();不支持时退至 input 事件手动清洗,并注意光标位置与中文输入法兼容性。

直接在 input 事件里调 preventDefault() 拦不住非法字符——因为字已经进去了,DOM 已更新,阻止毫无意义。真正能“拦在门外”的时机,是 beforeinput;实在不支持时,才退回到 input + 手动清理。
优先用 beforeinput 拦截(推荐)
现代浏览器(Chrome 62+、Edge 79+、Firefox 102+)都支持 beforeinput,它在字符真正插入前触发,且可被 preventDefault() 阻止:
-
event.data包含即将插入的原始文本(如用户按了“a”、粘贴了“abc”、IME 输入选中一个词) -
event.inputType告诉你操作类型:比如"insertText"、"insertFromPaste"、"deleteContentBackward" - 只对
inputType === "insertText" && event.data非空时做校验,避免误拦中文输入法的中间状态 - 对粘贴操作,需用
event.clipboardData?.getData("text/plain")提前读取并校验内容
旧浏览器降级方案(如 Safari ≤ 15.4)
这些浏览器不支持 beforeinput,只能监听 input 事件,在字符插入后立刻清洗:
- 用正则匹配并替换非法字符,例如:
value.replace(/[^a-zA-Z0-9_]/g, "") - 替换后光标会跳到末尾,若需保留原位置,得提前记录
selectionStart和selectionEnd,再用setSelectionRange恢复 - 该方式无法防止用户看到非法字符闪现一下,体验略差,但兼容性好
别踩这些坑
很多写法看似能用,实则不可靠:
-
onkeypress/keydown只能捕获按键,拦不住粘贴、拖放、IME 上屏、长按输入等场景 -
charCode已被弃用,Chrome 120+ 等新版浏览器可能不支持,不要依赖 -
pattern属性只在表单提交时校验,完全不阻止输入,也不能防粘贴 - 所有前端拦截都可被绕过,服务端必须用相同规则二次校验
金额/数字类输入要额外注意
比如只允许整数或两位小数,不能只拦字符,还要管结构:
- 小数点最多一个,且不能开头或结尾(除非是“0.”这种中间态)
- 小数位不能超过两位,粘贴“12.345”应自动截为“12.34”
- 整数部分不能以多个 0 开头(如“007”应转为“7”,但“0”本身合法)
- 建议内部维护无格式的
rawValue,显示层再加千分位和小数点,避免格式干扰逻辑
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











