type="number"不适合金额输入,因其在移动端和粘贴场景下校验不可靠;应改用type="text"配合键盘拦截与双值管理,确保精度、格式与光标控制。

直接用 type="number" + step="0.01" 不能可靠实现金额输入,尤其在移动端和粘贴场景下极易失效。真正可控的方案是放弃原生数字校验,改用 type="text" 配合键盘拦截与双值管理。
为什么 type="number" 不适合金额输入
浏览器对 type="number" 的实现差异大:iOS 允许粘贴 "1.234"、Android 可能忽略 step、Safari 对 pattern 完全不生效;value 返回字符串,需手动 parseFloat,但 "1.00" 会变成 1,丢失精度;微调器(上下箭头)无法禁用或定制,且不支持千分位显示。
-
step="0.01"仅约束增减操作和失焦校验,不阻止键盘手动输入非法值 -
pattern属性在type="number"下被忽略,无法补救 - 用户长按
.可能输入".."或"1..2",原生控件不拦截
用 type="text" + 键盘事件拦截的核心校验点
关键不是“禁止什么”,而是“只允许合法状态转移”。每次按键或粘贴后,立即提取纯数字结构,再按规则重建值。
- 小数点最多 1 个:已有
"."时,再按.直接event.preventDefault() - 小数点后最多 2 位:匹配
/^\d+(\.\d{0,2})?$/,超长则截断,如"12.345"→"12.34" - 整数部分不允许多余前导零:除非值就是
"0"或"0.x",否则"001"→"1","01.2"→"1.2" - 粘贴内容必须走相同校验:监听
paste事件,用event.clipboardData.getData('text')提取后清洗,再inputElement.setRangeText()写入
双值管理:rawValue 和 displayValue
界面显示带千分位和两位小数(如 "1,234.56"),但内部存储始终是原始数值或标准化字符串(如 "1234.56")。光标位置必须同步修正,否则 iOS 上输入会跳到末尾。
- 监听
input事件,从input.value中剥离格式(去逗号、去空格),得到rawValue - 用正则或
Intl.NumberFormat格式化为displayValue,再赋回input.value - 调用
inputElement.setSelectionRange()手动重置光标,位置按语义映射(例如在"1,2|34.56"中按"3",光标应停在"234"的"3"后) - 避免在
input中直接修改value后不更新光标——这是 iOS 光标乱跳的主因
最易被忽略的是粘贴和语音输入路径:它们完全绕过键盘事件,必须单独捕获 paste 和 input(后者可捕获语音转文字),且校验逻辑必须与键盘路径完全一致。服务端仍需做最终校验,因为任何前端控制都可被绕过。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











