全局过滤器必须在main.js中vue.filter()注册且位于new vue()前,否则小程序端静默失效;同名局部过滤器会完全替换全局版本而不报错;抽离为工具函数需兼顾多端兼容性并真机验证。

全局过滤器怎么注册才不会漏掉
所有页面都要用的过滤器,必须在 main.js 里用 Vue.filter() 注册,且要在 new Vue() 之前执行。漏掉这一步,哪怕写得再标准,H5 端可能有反应,小程序端直接静默失效——连控制台警告都没有。
常见错误是把注册逻辑写在 App.vue 的 onLaunch 里,或者塞进某个页面的 filters 选项中。这两种方式都只对局部生效,其他页面根本看不到这个过滤器。
- 注册位置必须是
main.js,紧挨着Vue.config.productionTip = false后面 - 函数名要语义清晰,比如
formatDate、truncateText,避免用filter1这类无意义命名 - 注册顺序无关紧要,但建议按字母或使用频率排序,方便后期维护
局部过滤器和全局同名时谁生效
如果某个页面在 filters 选项里定义了和全局同名的过滤器,比如都叫 priceFormat,那这个页面只会用自己定义的版本,全局的被完全屏蔽。这不是覆盖,是替换——而且不报错、不提醒。
这种“悄悄覆盖”特别容易引发线上问题:你在 A 页面调试时发现价格显示异常,查了半天全局过滤器逻辑是对的,最后才发现 B 页面自己重写了它,还少处理了负数场景。
- 跨页面复用逻辑,坚决不用局部定义;局部只放真正只在此页使用的临时转换
- 想确认某页面实际用的是哪个版本,可以在该页面
console.log(Vue.options.filters.priceFormat)(H5 可用) - 小程序端没法直接读
Vue.options,建议在注册时加console.log('global filter registered: priceFormat')打点
过滤器抽成工具函数后怎么再封装成过滤器
纯逻辑抽离到 utils/filters.js 是更可持续的做法。比如把日期格式化逻辑写成普通函数 formatDate(date, fmt),再在 main.js 里用它包装一层:
import { formatDate } from '@/utils/filters.js'
Vue.filter('formatDate', (value, fmt = 'yyyy-MM-dd') => {
return formatDate(value, fmt)
})
这样做的好处是:工具函数可被 computed、methods、甚至服务端直出调用;过滤器只是它的模板层适配入口,不承担核心逻辑。
- 别在工具函数里访问
this或组件实例,保持纯函数特性 - 参数默认值要和模板中常用写法对齐,比如
{{ time | formatDate('MM/dd HH:mm') }}能直接跑通 - 如果工具函数内部用了平台 API(如
uni.getSystemInfoSync),必须在外层过滤器中做平台判断,否则小程序编译会失败
为什么抽离后 H5 正常但小程序白屏
最常被忽略的一点:小程序平台不支持在过滤器函数体内动态 import 或调用未声明的 API。比如你把正则校验逻辑抽成工具函数,里面用了 new RegExp(pattern, 'u'),而某些低版本微信基础库不支持 unicode 标志位,就会在小程序里静默失败,渲染为空。
这不是抽离的问题,而是运行时环境差异没兜住。H5 浏览器能跑通的代码,在小程序真机上不一定行。
- 所有抽离的工具函数,必须在小程序真机上逐个验证,不能只靠 H5 预览
- 涉及正则、
Intl、atob等 API 的,统一加降级逻辑,比如try/catch后 fallback 到字符串截取 - 构建时开启
uni-app的「严格模式」("minifyJS": { "drop_console": false }),保留调试信息便于定位










