别在 filters 里写金额千分位逻辑——它在微信/支付宝/字节小程序中完全失效,H5 端仅 Vue 2 可用,Vue 3 已废弃 filters API;推荐使用 Intl.NumberFormat 封装函数,兼容性好、准确性高。

别在 filters 里写金额千分位逻辑——它在微信/支付宝/字节小程序里根本不会执行,H5 端也仅限 Vue 2 项目可用,Vue 3(即 uni-app 3.x 默认模式)已彻底移除 filters API。
uni-app 的 filters 在小程序端完全失效
你写了 Vue.filter('toThousands', ...),模板里写 {{ price | toThousands }},真机调试时没反应——不是代码错了,是编译阶段就被跳过。微信基础库、支付宝 SDK、抖音小程序运行时均不解析 WXML 中的 | 语法,filters 对象在小程序侧形同虚设。
- Vue 2 模式(
main.js中调用Vue.filter)仅 H5 有效,App 和小程序端无效 - Vue 3 模式(
createSSRApp+setup)下filters选项已被 Vue 官方废弃,uni-app 不做兼容 - 即使 H5 能跑,
toLocaleString()在部分安卓 WebView 中对zh-CNlocale 支持不稳定,可能返回无分隔符结果
可靠方案:用 Intl.NumberFormat 封装成函数
这是目前最省心、最准、跨端兼容性最好的方式。微信基础库 2.19.0+、支付宝 10.2.80+、H5 主流浏览器、App nvue(需确认基础库)均已支持。
- 必须先用
Number(value)转类型,传字符串会返回"Invalid" - 指定
minimumFractionDigits: 2确保补零,maximumFractionDigits: 2在低版本小程序中可能被忽略,建议统一用minimumFractionDigits+ 后续截断 -
'zh-CN'保证逗号分隔、小数点为分隔符;若需国际化,可动态传入uni.getLocale()或后端返回的 locale 字符串
const formatMoney = (value) => {
if (value == null || value === '') return '0.00'
const num = Number(value)
if (isNaN(num)) return '0.00'
return new Intl.NumberFormat('zh-CN', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}).format(num)
}
替代方案:正则 + toFixed(2) 手动处理(兼容极老基础库)
如果项目要支持微信基础库
- 别直接
(0.1 + 0.2).toFixed(2)→ 得到"0.30000000000000004",应先四舍五入:Math.round(num * 100) / 100 - 正则
/\B(?=(\d{3})+(?!\d))/g安全匹配整数部分内部位置,不影响负号和小数点 - 必须提前处理负号:提取符号 → 对绝对值格式化 → 拼回符号
- 后端返回空字符串、
null、带全角逗号的脏数据,都要在调用前清洗,否则toFixed报NaN
const toThousands = (value) => {
if (value == null || value === '') return '0.00'
let num = Number(value)
if (isNaN(num)) return '0.00'
const sign = num < 0 ? '-' : ''
num = Math.abs(num)
const fixed = Math.round(num * 100) / 100
return sign + fixed.toFixed(2).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
WXS 里做千分位?只适合纯展示列表,且不能响应变化
如果你在长列表(比如商品瀑布流)中每个 item 都要格式化价格,又担心 JS 层计算拖慢渲染,可以考虑 WXS。但它有硬限制:
- WXS 函数不能访问
this、data、methods,也不能触发响应式更新 - 不支持 ES6 可选链、空值合并、解构,连
console都没有,调试靠 return 插值观察 - 引入路径必须是相对路径,如
@/utils/format.wxs会被编译报错,得写成./format.wxs - 导出必须用
module.exports = { toCurrency: function() {...} },调用写法是{{ filters.toCurrency(item.price) }}
真正容易被忽略的是原始数据清洗——后端字段可能是字符串 "1999.9000"、"-1234.5"、"" 或 null,不做校验直接进 Intl.NumberFormat 或正则,结果就是 "Invalid" 或 "NaN.00"。格式化函数的第一行,永远应该是类型兜底。


















