过滤器必须在main.js中通过Vue.filter()全局注册才生效,仅创建文件不注册则模板中静默失败;跨端兼容性差,小程序等平台不支持,推荐改用utils目录下的纯函数配合computed使用。

过滤器文件放哪目录不重要,main.js 里注册才生效
只建 filters.js 文件、放进 common/ 或 utils/ 目录,但没在 main.js 中调用 Vue.filter(),就等于没写。模板中 {{ value | myFilter }} 会静默失败——不报错,也不渲染结果。
根本原因:uni-app(基于 Vue 2)的过滤器是全局注册机制,依赖 Vue.filter() 挂载到构造函数上,它不扫描目录、不识别文件名、不自动导入。
-
common/filters/index.js、utils/filters.js、甚至src/filters.js都可以,只要路径能被import到 - 推荐放在
utils/filters.js,与其它纯工具函数保持一致,符合多数项目结构习惯 - 避免放在
components/或pages/下——易被误认为是组件或页面,语义混乱
为什么不能只靠文件存在就自动加载
uni-app 启动流程中,main.js 是最早执行的 JS 入口,且必须在 new Vue({}) 之前完成所有 Vue.filter() 调用。如果把注册逻辑写在 App.vue 的 created 或某个页面的 onLoad 里,此时 Vue 实例已创建完毕,过滤器注册太晚,其他组件模板早已编译完成,无法生效。
- ❌ 错误位置:
App.vue、任意页面的script块、store初始化逻辑中 - ✅ 正确位置:
main.js开头,在new Vue()调用之前 - 注意:使用 vue-cli 或 vite 模式时,入口仍是项目根目录下的
main.js,不是src/main.js
跨平台时别依赖这个目录结构
Vue.filter() 在 H5 端有效,但在微信/支付宝小程序和 App 端基本不执行——各端底层渲染引擎不支持管道语法,uni-app 未做 polyfill。你在 utils/filters.js 里写的函数,小程序真机上可能直接原样输出 {{ date | formatDate }},或显示空字符串、NaN-NaN-NaN。
- 若项目需多端发布,不要把格式化逻辑只塞进
filters.js+Vue.filter() - 应改为导出纯函数(如
export const formatDate = (date) => { ... }),在setup或computed中显式调用 - 金额类场景优先用
Intl.NumberFormat,比手写过滤器更稳定、跨端兼容性更好
注册时最容易漏掉的两个细节
哪怕目录放对了、文件写对了、也 import 了,Vue.filter() 调用本身仍可能出错,导致过滤器“看起来注册了,实则无效”。
- 函数签名必须是
(value, args),第一个参数value不可省略——箭头函数写成(format) => {...}就会把模板传入的原始值丢掉 - 必须做
value的防御性判断:if (!value || isNaN(new Date(value).getTime())) return '',否则遇到null、''、非法时间字符串时,new Date()返回Invalid Date,后续调用getFullYear()报TypeError,页面白屏难定位
this 或 uni 对象,跨平台能力天然受限。与其纠结“该放哪个目录”,不如先确认你是否真的需要它——多数场景下,一个 utils/filters.js 里的纯函数,配合 computed 或 ref 显式调用,更可控、更易测、更少坑。


















