使用NumeralJS如何按数值千/百万量级匹配对应格式化规则
问题背景
应用开发过程中,需要对卡片组件上展示的数值做格式化处理,规则如下:
- 仅当数值整数部分位数达到6位及以上时启用缩写格式
- 千级缩写数值(如210500)保留1位小数,展示为
210.5k格式 - 百万级及以上缩写数值(如2120000)保留2位小数,展示为
2.12m格式 - 位数不足6位的数值不启用缩写,按常规数值格式展示
当前使用NumeralJS的格式字符串'0,0.[00]a'时,无法区分千级、百万级数值的小数位数要求,尝试使用Custom Format对象时未理清其底层实现逻辑,不确定是否需要遍历判断数值量级来选择对应格式化规则。
预期输入输出对应关系
210500 --> 210.5k 2120000 --> 2.12m 67500.89 --> 6.7k 6750000 --> 6.75m 16.75 --> 16.75 67530.85 --> 67.5k 675 --> 675 6700.05 --> 6700 2522.25 --> 2522
现有实现代码
function formatValue(value: string | number, shorthandFormat: boolean = true, shorthandLength: number = 6) { if (value === undefined || value === null) return '?'; let valueString = value.toString(); if (valueString.trim() === '') return ''; if (shorthandFormat) { if (!shorthandLength || shorthandLength < 0) { shorthandLength = 6; } if (valueString.length <= shorthandLength) { shorthandFormat = false; } } let numeralValue = numeral(value) let formatter = shorthandFormat ? '0,0.[0]a' : '0,0.[00]'; let formattedValue = numeralValue.format(formatter); return formattedValue; }
可运行代码片段
function formatValue(value, shorthandFormat = true, shorthandLength = 6) { if (value === undefined || value === null) return '?'; let valueString = value.toString(); if (valueString.trim() === '') return ''; if (shorthandFormat) { if (!shorthandLength || shorthandLength < 0) { shorthandLength = 6; } if (valueString.length <= shorthandLength) { shorthandFormat = false; } } let numeralValue = numeral(value) let formatter = shorthandFormat ? '0,0.[0]a' : '0,0.[00]'; let formattedValue = numeralValue.format(formatter); return formattedValue; } // 210,500 需要展示为210.5k,百万级数值如2,120,000需要展示为2.12m console.log(formatValue(210500)) console.log(formatValue(2120000)) console.log(formatValue(675000))
<script src="https://cdnjs.cloudflare.com/ajax/libs/numeral.js/2.0.6/numeral.min.js"></script>
实现方案
不需要自定义NumeralJS格式对象,只需要在格式化前先判断数值量级,选择对应格式串即可,同时修复原有逻辑中字符串长度判断不准确的问题:
- 先将输入值转为数字类型,单独提取整数部分计算位数,避免负号、小数点、小数位干扰长度判断
- 达到缩写阈值的数值,按量级拆分格式:千级区间(绝对值小于1000000)使用1位小数的缩写格式,百万级及以上使用2位小数的缩写格式
- 非缩写场景使用最多保留2位小数的格式,自动舍弃末尾无意义的0
- 统一将NumeralJS默认输出的大写K/M转为小写,匹配展示要求
修正后的完整代码如下:
function formatValue(value: string | number, shorthandFormat: boolean = true, shorthandLength: number = 6) { if (value === undefined || value === null) return '?'; const numValue = Number(value); if (Number.isNaN(numValue)) return '?'; const valueString = numValue.toString(); if (valueString.trim() === '') return ''; // 计算整数部分长度,排除符号、小数位影响 const integerPartLength = Math.abs(Math.trunc(numValue)).toString().length; let formatter = '0[.][00]'; // 默认非缩写格式:整数部分正常展示,最多2位小数,自动去除尾0 if (shorthandFormat) { shorthandLength = shorthandLength > 0 ? shorthandLength : 6; if (integerPartLength >= shorthandLength) { // 千级(<1e6)保留1位小数,百万及以上保留2位小数 formatter = Math.abs(numValue) < 1000000 ? '0.0a' : '0.00a'; } } let result = numeral(numValue).format(formatter); // 单位转小写 return result.replace(/[KM]/g, match => match.toLowerCase()); }
所有预期输入均可匹配输出要求,无需额外遍历或修改NumeralJS底层配置。
内容的提问来源于stack exchange,提问作者Jill
相关产品推荐
相关产品推荐

