Pinia 中不能直接使用 Vue.filter 注册的过滤器,因其是模板专属、全局注册机制,而 Pinia store 是纯 JS 对象,不参与模板编译;需将逻辑抽为可导入的纯函数(如 getStatusText),在 store 的 getter 中调用以实现响应式复用。

Pinia 里不能直接用 Vue.filter 注册的过滤器
Vue 2 的 Vue.filter 是全局注册、模板专属的机制,而 Pinia store 是纯 JS 对象,不参与 Vue 模板编译流程。你在 main.js 里注册了 statusText 过滤器,但在 Pinia 的 state 或 actions 里调用 statusText(0) 会报 ReferenceError: statusText is not defined——它根本不在作用域里。
真正能用的地方只有模板:{{ status | statusText }}。想在 Pinia 里复用相同逻辑,必须把映射逻辑抽出来,变成可导入的纯函数。
- 别在 store 文件里 import Vue 或试图访问
Vue.options.filters,H5 端可能临时可行,小程序端直接报错或 undefined - 不要写
this.$options.filters.statusText(value),Pinia 实例没有$options,也不该耦合 Vue 实例细节 - 推荐做法:新建
utils/statusMap.js,导出 const map 和 getLabel 函数,store 和组件都 import 它
在 store 中复用状态映射逻辑的正确姿势
比如用户状态码转文字,不要在 useUserStore 里硬编码 switch,而是复用同一份映射表:
// utils/statusMap.js
export const STATUS_MAP = {
'0': '正常',
'1': '待审核',
'2': '已拒绝',
'3': '已通过'
}
export function getStatusText(value) {
return STATUS_MAP[value] || '未知状态'
}
然后在 store 里直接调用:
// stores/user.js
import { defineStore } from 'pinia'
import { getStatusText } from '@/utils/statusMap'
export const useUserStore = defineStore('user', {
state: () => ({
status: '0',
profile: null
}),
getters: {
statusText: (state) => getStatusText(state.status)
},
actions: {
updateStatus(newCode) {
this.status = newCode
// 如果需要同步更新本地存储(如 token 变更触发状态刷新),这里可以加逻辑
uni.setStorageSync('user_status', newCode)
}
}
})
- getters 是响应式的,
{{ user.statusText }}在模板中会自动更新 - 如果映射需国际化,
getStatusText应接收 locale 参数,并从i18n.messages[locale]读取,而非在函数内调用this.$t - 避免在
actions内部做格式化并存入 state(如this.statusText = getStatusText(v)),这违反单一数据源原则,且易与原始值不同步
模板里混用 Pinia 和过滤器时的常见失效点
你可能写了 {{ user.status | statusText }},但发现没生效——不是过滤器写错了,而是值本身有问题:
-
user.status是undefined或null:过滤器返回空字符串,页面显示空白,控制台无报错 - 后端传的是数字
0,但过滤器 map key 是字符串'0',匹配失败 → 返回 '未知状态';务必统一类型,建议后端传字符串,或在 store 初始化时String(raw)转换 - Pinia store 尚未初始化完成,
user是 undefined,模板里{{ user?.status | statusText }}仍会因管道符左侧为 undefined 导致整个表达式静默失败(Vue 2 行为) - 用了
v-if="user"包裹再用{{ user.status | statusText }},但忘记在setup中提前调用useUserStore(),导致user始终是空对象
为什么不用 computed + 过滤器函数替代?
有人试过在组件里写:const statusText = computed(() => getStatusText(user.status)),再 {{ statusText }}。这确实可行,但多此一举:
- Pinia 的 getter 已天然具备 computed 行为,且跨组件共享,无需每个页面重复定义
- 如果多个页面都要展示
user.statusText,分散在各组件里写 computed,不如统一收口到 store,维护成本更低 - 过滤器函数本身无副作用、无依赖,作为工具函数复用比塞进组件更干净
- 真要动态参数(如带单位的金额格式化),应封装成带参数的工具函数,例如
formatAmount(value, unit = '元'),而不是强行塞进过滤器链
最易被忽略的是:状态映射逻辑一旦写死在模板过滤器里,就和视图强绑定,后续要做服务端渲染、单元测试或导出 CSV 时,这部分逻辑就散落各处没法复用。抽成工具函数,才是面向变化的设计。


















