过滤器不支持条件编译,因filters是运行时对象而条件编译仅在编译期生效;正确做法是将过滤器注册逻辑移至main.js或onLoad中用条件编译控制,或改用方法封装平台差异。

过滤器本身不支持条件编译
uni-app 的 filters 选项是运行时逻辑,而条件编译(// #ifdef)只在编译阶段生效——它不能嵌入 filters 对象内部。你写不了这样的代码:
filters: {
// #ifdef MP-WEIXIN
formatName(value) { return 'wx-' + value }
// #endif
// #ifdef H5
formatName(value) { return value.toUpperCase() }
// #endif
}这会直接导致编译失败或静默忽略,因为 filters 是一个 JS 对象字面量,不是可被注释切割的代码块。
正确做法:用条件编译包裹过滤器注册逻辑
把过滤器定义从 filters 选项里移出来,改到 main.js(全局)或组件的 created/onLoad(局部)中,再用条件编译控制注册分支:
- 全局注册(推荐):在
main.js中按平台注册不同实现 - 局部注册:在页面
onLoad里判断平台后动态挂载函数到this.$options.filters(不推荐,维护成本高) - 更稳妥的替代:根本不用过滤器,改用计算属性或方法 + 条件编译封装逻辑
例如,在 main.js 中:
// #ifdef MP-WEIXIN
Vue.filter('formatTime', (ts) => wx.formatTime(ts, 'yyyy-MM-dd'))
// #endif
// #ifdef H5
Vue.filter('formatTime', (ts) => new Date(ts).toLocaleDateString())
// #endif
// #ifdef APP-PLUS
Vue.filter('formatTime', (ts) => uni.timeFormat(ts, 'Y-M-D'))
// #endif为什么别在模板里用条件编译套过滤器
有人试图这样写:
<!-- #ifdef MP-WEIXIN -->
{{ time | wxFormatTime }}
<!-- #endif -->
<!-- #ifdef H5 -->
{{ time | h5FormatTime }}
<!-- #endif -->这看似可行,但实际埋了三个坑:
- 所有平台都会打包进两个过滤器函数,哪怕只用一个——白占包体积
- 如果某个平台没注册对应过滤器(比如漏写了
// #ifdef APP-PLUS分支),运行时就静默渲染为空,极难排查 - 模板层逻辑分散,同一语义(格式化时间)被拆成多个过滤器名,违反单一职责
真正轻量且可控的方案:用方法 + 条件编译
把平台差异收口到一个方法里,模板只调一次,清晰又安全:
methods: {
formatTime(ts) {
// #ifdef MP-WEIXIN
return wx.formatTime(ts, 'yyyy-MM-dd')
// #endif
// #ifdef H5
return new Date(ts).toLocaleDateString()
// #endif
// #ifdef APP-PLUS
return uni.timeFormat(ts, 'Y-M-D')
// #endif
}
}然后模板中统一写:{{ formatTime(time) }}。这样:
- 编译后每个平台只保留自己那一段逻辑,无冗余
- 类型安全:IDE 能识别
formatTime是一个函数,不会误判为未定义 - 调试友好:加一行
console.log就能确认当前走的是哪条分支
注意:这个方法必须确保参数非空,否则各平台 API 可能抛错(比如 wx.formatTime(undefined) 会报错,而 uni.timeFormat 可能返回空字符串)。


















