Vue输入框金额格式化:显示格式化值但保留原始数值
解决方案
核心思路
不能直接用v-model绑定原始存储值,因为v-model是双向绑定会同步修改原始数据。需要将显示值和存储值分离:用独立变量维护输入框的格式化显示内容,输入时将内容还原为纯数字存入原始对象,同时更新显示值为格式化后的结果。
具体实现步骤
- 新增两个独立的响应式变量,用于绑定输入框的显示内容
- 编写格式化/反格式化工具函数:
- 格式化函数:将纯数字转为带千分位、货币符号的字符串
- 反格式化函数:将用户输入的格式化字符串还原为纯数字
- 拆分
v-model为:value(绑定显示值)和@input(处理输入逻辑) - 监听原始存储值的变化,同步更新显示值(应对初始赋值或外部修改场景)
完整代码示例
模板部分
<div class="budget info" :class="{ 'input-error': inputsValid.budget }"> <label>Budget</label> <input type="text" :value="displayBudget" @input="handleBudgetInput" > </div> <div class="area info" :class="{ 'input-error': inputsValid.area }"> <label>Area</label> <input type="text" :value="displayArea" @input="handleAreaInput" > </div>
脚本部分
import { ref, watch } from 'vue' const info = ref({ budget: '', area: '', }) // 维护输入框的显示值 const displayBudget = ref('$0.00') const displayArea = ref('') // 格式化工具:货币格式(千分位+美元符号) const currencyFormatter = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }) // 格式化工具:数字千分位分隔(用于面积) const numberFormatter = new Intl.NumberFormat('en-US') // 反格式化:提取纯数字 const unformatNumber = (str) => { if (!str) return '' // 移除所有非数字和小数点的字符 const pureNum = str.replace(/[^0-9.]/g, '') // 处理多个小数点的情况 return pureNum.indexOf('.') !== pureNum.lastIndexOf('.') ? pureNum.slice(0, pureNum.indexOf('.')) + pureNum.slice(pureNum.indexOf('.')) : pureNum } // Budget输入处理 const handleBudgetInput = (e) => { const rawValue = unformatNumber(e.target.value) // 更新原始存储值 info.value.budget = rawValue // 更新显示值:如果是空值显示$0.00,否则格式化 displayBudget.value = rawValue ? currencyFormatter.format(rawValue) : '$0.00' // 验证逻辑 inputsValid.budget = rawValue === '' } // Area输入处理 const handleAreaInput = (e) => { const rawValue = unformatNumber(e.target.value) // 更新原始存储值 info.value.area = rawValue // 更新显示值:空值显示空,否则加千分位 displayArea.value = rawValue ? numberFormatter.format(rawValue) : '' // 验证逻辑 inputsValid.area = rawValue === '' } // 监听原始值变化,同步显示值(比如从后端加载数据时) watch(() => info.value.budget, (newVal) => { displayBudget.value = newVal ? currencyFormatter.format(newVal) : '$0.00' }) watch(() => info.value.area, (newVal) => { displayArea.value = newVal ? numberFormatter.format(newVal) : '' }) // 初始化验证状态(根据原有逻辑调整) const inputsValid = ref({ budget: info.value.budget === '', area: info.value.area === '' })
关键细节说明
- 把Budget输入框的
type="number"改为type="text":因为number类型输入框无法显示带货币符号、千分位的格式化字符串 - 反格式化函数会过滤所有非数字和小数点的字符,确保存入info的是纯数字字符串
- 通过watch监听info的原始值,确保外部修改原始数据时,输入框显示也会同步更新
- 验证逻辑直接基于原始存储值判断,避免受格式化显示值的影响
内容的提问来源于stack exchange,提问作者Jose
相关产品推荐
相关产品推荐

