如何在React Hook Form手机号输入框中禁止输入“e”和“-”字符?
问题根因
原生设置type="number"的输入框,浏览器本身就会放开科学计数法相关的输入许可——也就是字符e、正负号+/-、小数点.,这些是浏览器层面的内置行为,不是控件的bug。
你当前的拦截逻辑完全失效,核心问题有两个:
- 正则判断逻辑错位:
/[^e]/.test(e.target.value)的判断规则是“输入值中存在任意非e的字符就返回true”,只要你输入的内容不是纯e,不管里面夹杂多少e、-都会触发onChange,根本起不到拦截作用 - 拦截范围过窄:正则只排除了e,完全没覆盖-、小数点等其他非法字符,再加上没做空值兜底,很容易出现输入卡滞、值不同步的运行异常。
可落地的解决方案
方案1(最优推荐)
做手机号输入不需要强依赖type="number"属性,替换成文本类型+数字键盘属性,从根源规避非法字符输入入口:
- 把输入框的
type从number改成text - 增加
inputMode="numeric"属性,手机端会直接唤起纯数字键盘,没有e、-等字符的输入入口 - 在onChange逻辑里统一做字符过滤,仅保留0-9的数字
完整可运行代码如下:
<Controller name="phone" control={control} rules={{ required: '请输入手机号', pattern: /^1[3-9]\d{9}$/, }} render={({ onChange, value, ref }) => ( <Input ref={ref} type="text" inputMode="numeric" label="手机号" maxLength={11} onChange={(e) => { // 正则替换掉所有非数字字符,过滤所有非法输入 const filteredValue = e.target.value.replace(/\D/g, '') onChange(filteredValue) }} val={value ?? ''} /> )} />
方案2(必须保留number类型时的适配方案)
如果业务场景要求必须保留type="number"属性,需要做三层适配,解决运行异常问题:
- 替换原有的错误onChange判断逻辑,用字符替换的方式过滤所有非数字内容,不要用test判断做分支拦截
- 增加onKeyDown事件,从键盘输入层直接阻断e、-等非法字符的输入
- 给输入框的展示值加空值兜底,避免number类型控件把空值默认显示为0
核心适配代码片段:
<Input ref={ref} type="number" label="手机号" onChange={(e) => { // 过滤掉e、-、+、.等所有非数字字符 const filteredValue = e.target.value.replace(/[^\d]/g, '') onChange(filteredValue) }} onKeyDown={(e) => { // 拦截非法字符的键盘输入 const forbiddenKeys = ['e', 'E', '-', '+', '.'] if (forbiddenKeys.includes(e.key)) { e.preventDefault() } }} // 空值兜底,避免显示默认0 val={value ?? ''} />
内容的提问来源于stack exchange,提问作者zagoor
相关产品推荐
相关产品推荐

