全局 filter 必须在 main.js 中通过 Vue.filter() 显式注册,仅创建文件无效;需 import 后批量注册,函数签名必须为 (value, ...args),禁止使用平台 API 或异步操作。

全局 filter 必须在 main.js 中注册,不能只靠文件存在就生效
uni-app 的过滤器(filter)不是“放对位置就能自动加载”的资源。哪怕你新建了 common/filters/index.js,只要没在 main.js 里显式调用 Vue.filter(),所有页面里的 {{ value | myFilter }} 都会静默失败——不报错,但也不渲染结果。
根本原因:Vue 2(当前绝大多数 uni-app 项目所用)的 filter 是全局注册机制,依赖 Vue.filter 方法挂载到 Vue 构造函数上;它不扫描目录、不自动 import、不识别文件名约定。
- ✅ 正确做法:在
main.js开头 import 过滤器定义,再逐个注册 - ❌ 错误做法:只建
filters/目录、写好函数、却忘了在main.js调用Vue.filter - ⚠️ 注意:
App.vue或任意页面的created/onLoad里调用Vue.filter无效——此时 Vue 实例已创建,注册太晚
Vue.filter() 注册时参数顺序和类型必须严格匹配
常见错误是把过滤器函数写成箭头函数并漏掉第一个参数(即被处理的原始值),导致 value 变成 undefined。
比如这个写法是错的:
Vue.filter('formatDate', (format) => { // ❌ 缺少 value 参数
return new Date().toLocaleDateString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit' })
})
正确签名必须是 (value, ...args):
Vue.filter('formatDate', (value, format = 'yyyy-MM-dd') => {
if (!value) return ''
const d = new Date(value)
const year = d.getFullYear()
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
if (format === 'yyyy-MM-dd') return `${year}-${month}-${day}`
return d.toLocaleDateString('zh-CN')
})
- 第一个参数
value是模板中管道符左边传入的值,不可省略 - 后续参数(如
format)才对应模板中| formatDate('MM/dd/yyyy')的传参 - 务必做
!value判断——时间戳可能为null、''、0,直接new Date(null)会得 Invalid Date
跨平台兼容性:避免在 filter 内部调用平台专属 API
过滤器函数运行在所有平台(H5、微信小程序、App),但它的执行环境不是组件实例上下文,没有 this,也没有 uni 对象的自动注入。所以不能在 filter 里写 uni.getSystemInfoSync() 或 document.querySelector。
典型报错:
- H5 正常,小程序编译时报
ReferenceError: document is not defined - App 端运行时报
uni is not defined
解决办法只有两个:
- 过滤器纯数据处理:只用 JS 原生方法(
Date、String.prototype、Number等) - 需要平台判断的逻辑,必须提前在页面 data/computed 里处理好,再传给模板——filter 不负责 IO 或环境探测
推荐目录结构与导入写法:保持可维护性
虽然注册必须在 main.js,但把所有 filter 函数堆在 main.js 里会导致文件臃肿、难复用、IDE 提示差。推荐拆分:
1. 创建 common/filters/index.js,统一导出对象:
export const filters = {
formatDate(value, format) {
// 实现同上
},
toFixed2(value) {
return Number(value).toFixed(2)
}
}
2. 在 main.js 中批量注册:
import Vue from 'vue'
import { filters } from '@/common/filters'
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
- 这样既保持逻辑分离,又确保注册时机正确
- 后续加新 filter,只需在
filters/index.js的对象里加一项,不用改main.js - 注意路径别写成
./common/filters—— uni-app 中@/指向src/,这是 HBuilderX 和 vue-loader 默认别名


















