Vue.js 提供过滤器主要用于模板中的文本格式化,它不会改变原始数据,只影响展示结果。过滤器在 Vue 2 中被大量使用,比如格式化日期、金额、首字母大写、状态码映射等场景都能看到它的身影。不过到了 Vue 3,官方已经移除了过滤器特性,转而推荐使用计算属性或方法。这篇文章会围绕自定义过滤器的定义、全局与局部注册、传参、链式使用以及常见报错展开,并结合迁移示例说明 Vue 3 项目的替代方案。

一、自定义过滤器的基本概念与注册方式
在 Vue 2 中,过滤器本质上是一个接收输入值并返回处理结果的函数。模板里通过管道符 | 来使用,例如 {{ message | capitalize }}。它只能用在插值表达式和 v-bind 表达式中,不能用在 v-model、v-on 这类涉及双向绑定或事件监听的指令上。理解这一点非常关键,因为很多看起来合理的需求,比如在输入框中边输入边格式化,实际上并不适合用过滤器实现。
注册过滤器分为全局注册和局部注册。全局注册通过 Vue.filter 方法,适用于所有组件共享的格式化逻辑;局部注册则在组件的 filters 选项中定义,只对当前组件生效。两种方式可以同时存在,重名时局部过滤器优先级更高。下面是一个全局过滤器的示例:
// 全局注册首字母大写过滤器
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
new Vue({
el: '#app',
data: {
name: 'vue.js'
}
})
局部注册的写法如下,过滤器函数放在组件配置对象的 filters 字段中:
export default {
data() {
return {
price: 99.9
}
},
filters: {
formatPrice(value) {
return '¥' + Number(value).toFixed(2)
}
}
}
需要留意,过滤器函数内的 this 并不指向当前组件实例,而是指向 undefined 或全局对象。如果过滤逻辑依赖组件数据,应当通过参数显式传入,或者在计算属性中完成格式化。这也是过滤器区别于 methods 的一个重要特征。
二、过滤器传参、链式调用与适用边界
过滤器支持传参,语法为 {{ value | filterName(arg1, arg2) }}。过滤器函数的第一个参数永远是被格式化的值,后面的参数按照模板中的顺序传入。例如日期格式化过滤器可以把格式字符串作为第二参数:
Vue.filter('formatDate', function (date, pattern) {
if (!date) return ''
const d = new Date(date)
const y = d.getFullYear()
const m = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
if (pattern === 'yyyy-MM-dd') {
return `${y}-${m}-${day}`
}
return `${y}/${m}/${day}`
})
// 模板中使用
// {{ createTime | formatDate('yyyy-MM-dd') }}
链式调用同样常用。多个过滤器用管道符串联时,前一个过滤器的返回值会作为下一个过滤器的输入值。例如 {{ text | lowercase | truncate(10) }} 会先执行 lowercase,再把结果传给 truncate 并截取前 10 个字符。链式调用让模板表达式保持了简洁,但如果链条超过三个,建议把逻辑拆到方法或计算属性中,否则可读性会明显下降。
过滤器适合纯展示层的格式化工作,像金额千分位、时间格式化、状态码映射这类场景非常合适。但它不能处理异步请求,不能在内部修改响应式数据,也不能使用 this 访问组件上下文。遇到需要请求字典接口翻译状态的场景,就不应该强行使用过滤器,而是用异步方法或 watch 来处理。
三、常见问题解答与 Vue 3 迁移方案
问:为什么在 Vue 3 项目里使用过滤器会报错?原因很简单,Vue 3 已经移除了过滤器 API。官方认为过滤器的功能可以被计算属性或普通方法完全替代,而且计算属性在缓存、类型推断、tree-shaking 方面表现更好。解决办法是在模板里直接调用方法,例如 {{ capitalize(name) }},或者定义一个计算属性 formattedName 来使用。需要注意 Vue 3 中模板调用的方法不会自动缓存结果,频繁更新时可以用计算属性优化。
如果旧项目从 Vue 2 升级到 Vue 3,可以通过全局属性挂载一个格式化对象,在模板中调用。下面是一个简单的替换示例:
// Vue 3 替代过滤器的写法
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 全局方法,模板中可直接调用
app.config.globalProperties.$filters = {
capitalize(value) {
if (!value) return ''
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
// 组件模板中使用
// {{ $filters.capitalize(name) }}
另一个常见问题是过滤器在 v-bind 中能否使用。答案是 Vue 2 中可以,比如 <img :src="url | addPrefix">,但仍然受限于纯展示。还有开发者遇到过滤器接收不到参数的情况,通常是因为模板中漏写括号或者参数名与保留字冲突。检查过滤器函数定义与调用参数数量是否对应即可。
对于仍然使用 Vue 2 的团队,建议定期梳理项目里的过滤器,如果发现某个过滤器同时依赖多个组件状态,或者内部逻辑越来越复杂,就应当及时重构成工具函数或计算属性。对于已经迁移到 Vue 3 的项目,可以直接把需要复用的格式化逻辑抽到独立模块,再通过 setup 返回给模板使用。
Vue.js自定义过滤器Vue过滤器前端开发修改时间:2026-09-28 08:10:00