在开发一个订单预算系统 时,我们需要在前端动态计算「利润率差额」,格式为百分比(带 % 符号)保留4位小数 ,但实际传给后端时必须是纯数字(浮点数) ,以便后端正常以 BigDecimal
类型接收并处理。
然而,我们在某次提交数据到后端时,系统直接抛出以下异常:
告诉我们传递的是null ,告诉我无法转换
问题分析
前端相关代码如下所示:
html
// 利润率差额 profitRateDiff(百分比 + % 符号,保留4位小数)
const orderRevenueActual = Number(this.costData.orderRevenueActual) || 0
let profitRateDiff = '0.0000%' // 👈 注意这里是字符串!
if (orderRevenueActual !== 0) {
const rate = (netProfitDiff / orderRevenueActual) * 100
profitRateDiff = `${rate.toFixed(4)}%`
}
this.$set(this.costData, 'profitRateDiff', profitRateDiff)
这段代码表面上看没毛病,逻辑严谨,结果也是正确显示出"28.4212%"这样格式化的字符串。
然而,致命问题在于:
👉 profitRateDiff
被直接设置为 字符串类型(带 %)
👉 最终提交接口时 this.costData.profitRateDiff
仍是字符串 "28.4212%"
👉 后端尝试将 "28.4212%"
转换为 BigDecimal
,但 %
字符不是合法数字格式
👉 报错!
正确写法
1. 存值用数字,不要包含 %
字符,如果需要可以重新写个方法转过去
html
const orderRevenueActual = Number(this.costData.orderRevenueActual) || 0
let profitRateDiff = 0 // 👈 注意初始化为数字
if (orderRevenueActual !== 0) {
const rate = (netProfitDiff / orderRevenueActual) * 100
profitRateDiff = +rate.toFixed(4) // 强转为小数数字
}
this.$set(this.costData, 'profitRateDiff', profitRateDiff) // 仍是纯数字
比如:
html
methods: {
formatPercent(value) {
if (value == null || isNaN(value)) return '0.0000%'
return value.toFixed(4) + '%'
}
}
最佳实践总结
需求 | 实现方式 |
---|---|
存储 | 使用数字 28.4212 |
展示 | 格式化显示为 28.4212% |
提交后端 | 保证 costData.profitRateDiff 是数字类型 |
写在最后
这次坑给我们的经验是:
-
前端显示归显示,存储归存储,一定要分离
-
在与后端协作中,要严格约定字段类型:数字就是数字、字符串就是字符串
-
对格式化展示的字段,尽量使用计算属性、方法或者过滤器处理,而不要将格式化后的值直接赋值到数据模型中