uni-app全局filter必须在main.js中显式注册,否则静默失效;需按(value, ...args)签名编写纯同步函数,禁止调用uni、this等跨端不兼容API,且须导出为对象以便批量注册。

uni-app全局filter必须在main.js里注册,否则静默失效
只新建filters.js文件、写好函数,但没在main.js中调用Vue.filter(),所有页面里的{{ value | myFilter }}都不会生效——不报错,也不渲染。这是因为 Vue 2(uni-app 当前主流版本)的 filter 是构造函数级的全局注册机制,不会自动扫描或加载文件。
常见错误包括:
- 把
filters.js放在utils/或common/目录下就以为“放对位置就能用” - 在
App.vue的created钩子或某个页面里调用Vue.filter()——此时 Vue 实例已创建,注册太晚,无效
✅ 正确做法:在main.js最顶部 import 过滤器对象,再循环注册:
import filters from '@/utils/filters'
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
filter函数签名必须是(value, ...args),不能省略value
模板中{{ time | formatDate('MM/dd/yyyy') }}传入的time会作为第一个参数自动注入。如果过滤器函数漏掉这个value,比如写成(format) => {...},结果就是value为undefined,后续new Date(undefined)返回Invalid Date,最终渲染为空字符串或NaN。
务必遵守签名规范:
- 第一个参数必须是被处理的原始值(
value),不可省略、不可重命名 - 后续参数才对应模板中管道符后的传参,如
| phoneMask(3, 4)→(value, startLen = 3, endLen = 4) - 所有参数都要做防御性判断:空字符串、
null、0、undefined都可能传进来
示例(安全的时间格式化):
export default {
formatDate(value, format = 'yyyy-MM-dd') {
if (!value) return ''
const d = new Date(value)
if (isNaN(d.getTime())) return ''
// ... 格式化逻辑
}
}
filter内禁止调用uni、this、document等平台专属API
过滤器运行时没有组件实例上下文,this为undefined,uni未注入,document在小程序/APP端不存在。任何试图在 filter 里调用uni.getSystemInfoSync()、uni.showToast()或document.querySelector()的行为,都会在非 H5 平台直接报错或静默失败。
能做的只有纯计算类操作:
- 字符串处理(截取、替换、大小写转换)
- 数字格式化(千分位、小数点、百分比)
- 日期格式化(仅基于
Date原生 API) - 状态码映射(如
1 → '待付款')
跨端不兼容的典型误用:
// ❌ 错误:uni未定义,小程序里直接崩溃
phoneMask(value) {
const info = uni.getSystemInfoSync() // 报错!
return value.replace(/^(d{3})d+(d{4})$/, '$1****$2')
}
<p>// ✅ 正确:只做纯逻辑
phoneMask(value, startLen = 3, endLen = 4) {
if (!value || typeof value !== 'string') return ''
const reg = new RegExp(<code>^(\d{${startLen}})\d+(\d{${endLen}})$</code>)
return value.replace(reg, <code>$1****$2</code>) || value
}
推荐的filters.js结构:按功能拆分 + 导出对象
不要把所有 filter 写成一个大函数,也不要用export default function单个导出——那样无法批量注册。应统一导出一个 plain object,键名为 filter 名,值为函数。
建议目录结构:src/utils/filters.js
export default {
// 时间格式化
formatDate(value, format = 'yyyy-MM-dd') { /* ... */ },
<p>// 手机号脱敏
phoneMask(value, startLen = 3, endLen = 4) { /<em> ... </em>/ },</p><p>// 金额千分位
toCurrency(value, digits = 2) { /<em> ... </em>/ },</p><p>// 状态映射
orderStatus(value) {
const map = { 1: '待付款', 2: '待发货', 3: '配送中', 4: '已完成' }
return map[value] || '未知状态'
}
}
注意:所有函数必须是同步纯函数,不能含await、Promise、setTimeout等异步操作——filter 不支持异步返回。
真正容易被忽略的一点:filter 的执行时机在模板编译阶段,它不参与响应式依赖收集。如果 value 是响应式数据,filter 函数本身不会触发重新执行——但 Vue 会自动在 value 变化时重跑整个 filter,所以你不需要手动处理响应式逻辑;但千万别在里面搞副作用(比如发请求、改 state),那会失控。


















