输入框自动格式化需实时监听输入、清洗内容、重组显示并同步光标。vue用自定义指令、react用useeffect+useref、flutter用textinputformatter实现,均需处理粘贴、光标偏移、退格及国际号码适配。

用指令实现输入框自动格式化,核心是“监听输入 → 清洗内容 → 重组显示 → 同步光标”,而不是等用户输完再处理。关键在于实时、轻量、不干扰操作体验。
Vue 中用自定义指令实现手机号 3-4-4 格式化
指令能复用在任意 <input> 上,无需封装组件,适合快速落地:
- 监听
input事件,拿到原始输入值 - 用正则提取纯数字:
value.replace(/\D/g, '') - 截取前 11 位,按位置插入短横线:
138-1234-5678 - 手动设置
input.value并调用setSelectionRange修复光标偏移(尤其在中间删除时) - 绑定时支持传参,比如
v-phone-format="'CN'",为后续国际化留扩展
React 中用 useEffect + useRef 实现信用卡号空格分隔
不依赖第三方库,纯原生逻辑即可完成常见卡号格式(如 4512 3456 7890 1234):
- 用
useRef持有 input DOM 引用,避免闭包旧值问题 - 在
useEffect中监听 value 变化,先去除非数字字符 - 每 4 位插入一个空格,但只在长度 ≥4 时才开始加空格,避免开头冗余
- 计算光标在格式化后的新位置:原位置前有几个空格,新位置就加几
- 用
inputRef.current.setSelectionRange()主动重置光标,防止跳到末尾
Flutter 中用 TextInputFormatter 自定义手机号格式器
这是平台原生推荐方式,不侵入 UI 层,与键盘、粘贴、长按选择完全兼容:
- 继承
TextInputFormatter,重写formatEditUpdate - 从
newValue.text提纯数字,限制总长 ≤11 - 拼接格式字符串:
${digits.substring(0,3)}-${digits.substring(3,7)}-${digits.substring(7)} - 关键细节:当用户在第 4 位删掉一个数字时,要自动删掉前面的短横线,否则会变成
138--234-5678 - 组合使用:
[PhoneNumberFormatter(), LengthLimitingTextInputFormatter(11)],顺序不能错
通用避坑要点
无论哪种框架,以下问题高频出现,必须提前处理:
-
粘贴内容未过滤:监听
paste事件,event.preventDefault()后读取剪贴板文本并清洗 - 光标乱跳:格式化后必须同步更新光标位置,否则用户无法连续编辑中间段
-
退格键异常:在带分隔符的位置按退格,应优先删分隔符,再删数字(如
138-123|4-5678→138-12|34-5678) -
区域适配缺失:+86 是 11 位,+1 是 10 位,+44 是 11 位但结构不同,建议接入
libphonenumber-js做底层解析










