过滤器函数里拿不到 this 是 vue 的设计限制,因 filters 是纯函数、不绑定组件实例,无法访问 data、methods、computed 等上下文,应改用 computed、methods 或 composition api 中的自定义 hook 替代。

过滤器函数里拿不到 this,不是 bug,是 Vue 的设计限制 —— 过滤器(filter)在 Vue 2 和 uni-app 中本身就是纯函数,不绑定组件实例上下文。
为什么 filter 里不能用 this?
Vue 的 filters 选项定义的函数,在模板中被调用时,不会自动绑定 this。它只接收传入的参数,比如 {{ msg | formatText }} 中,formatText 只拿到 msg 的值,其他 data、methods、computed 都不可见。
常见错误现象:
- 在 filter 函数里写
this.$t('xxx')报错Cannot read property '$t' of undefined - 想用
this.userInfo.name做格式化,结果直接undefined - 试图访问
this.$store.state或getApp().globalData,全失败
替代方案:用 computed 或 methods 替代 filter
uni-app(尤其是 Vue 2 版本)仍支持全局/局部 filter,但一旦涉及上下文依赖,就得换路子。
- 把逻辑移到
computed:适合依赖响应式数据的场景,比如{{ formattedTitle }}对应computed: { formattedTitle() { return this.$t(this.title) + '!' } } - 改用
methods:更灵活,可传多参、调 API、判空,比如{{ formatWithUser(title, userInfo) }} - 避免在 template 里硬塞复杂逻辑:像
{{ item | formatDate | highlight | truncate(20) }}这种链式 filter,容易失控;拆成computed或提前在data里加工好
如果非要用 filter,怎么绕过 this 限制?
只能靠“把需要的东西提前传进去”,不能指望 filter 自己去拿。
- 显式传参:比如
{{ msg | formatText($t, userInfo) }},但注意$t是函数,userInfo是对象,得确保它们在调用时已存在 - 用闭包预置依赖:在
created或mounted里动态注册 filter,利用作用域捕获this,例如:created() { this.$options.filters.formatTime = (val) => { return this.$dayjs(val).format('YYYY-MM-DD') } }(注意:这种写法只对当前组件生效,且不能在data初始化前调用) - 全局 filter 别碰上下文:
Vue.filter('upper', str => str?.toUpperCase())这类纯转换可以,但别往里塞this.xxx
Vue 3 + Composition API 下 filter 已被移除
uni-app 的 Vue 3 项目(如使用 @dcloudio/uni-cli-vue3)根本不再支持 filters 选项 —— 官方明确废弃。此时必须用:
-
computed+ref/reactive - 自定义 hook(如
useFormat()),把 i18n、store、工具函数都封装进去 - 模板中直接调用函数:
{{ formatText(title, locale) }},前提是函数已在setup()中返回或导入
真正容易被忽略的是:很多人以为只是“写法变了”,其实底层机制已不同 —— Vue 3 的响应式系统不给 filter 留入口,强行模拟反而增加维护成本。










