在 Vue 2 时代,过滤器(Filter)是前端开发者处理文本格式化、数据展示的常用工具;而进入 Vue 3,这个曾经高频使用的 API 被彻底移除。很多从 Vue 2 迁移的开发者会疑惑:过滤器到底是什么?Vue 3 为什么要删掉它?没有过滤器该怎么实现数据格式化?
本文将用通俗易懂的语言,完整拆解 Vue 过滤器的核心知识、移除原因,并给出 Vue 3 官方推荐的替代方案,帮你彻底搞定这个 Vue 升级中的关键变更。
一、什么是 Vue 过滤器(Filter)?
1. 核心定义
Vue 过滤器是Vue 2 提供的文本格式化工具,本质是一个纯函数,接收原始数据作为参数,经过处理后返回格式化后的结果,不修改原始数据,只改变展示形式。
它主要用在两个场景:
- 双大括号插值
{{ }} v-bind表达式
调用时通过管道符
| 连接数据与过滤器,语法简洁直观。2. Vue 2 中过滤器的基本用法
(1)局部过滤器
仅在当前组件内使用,定义在组件的
filters 选项中:vue
<template>
<!-- 管道符调用:原始数据 | 过滤器名 -->
<div>{{ price | formatPrice }}</div>
</template>
<script>
export default {
data() {
return {
price: 99.8
}
},
// 局部过滤器
filters: {
formatPrice(value) {
// 空值处理
if (!value) return '¥0.00'
// 格式化价格,保留两位小数
return '¥' + value.toFixed(2)
}
}
}
</script>
(2)全局过滤器
在
main.js 中注册,整个项目所有组件都能直接使用:javascript
运行
// main.js
import Vue from 'vue'
// 全局过滤器:首字母大写
Vue.filter('capitalize', function(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
(3)高级用法
- 过滤器传参:支持传递额外参数,灵活适配不同场景
- 过滤器串联:多个过滤器依次处理数据,按从左到右执行
二、Vue 3 为什么彻底移除过滤器?
Vue 官方在迁移指南中明确说明:过滤器是设计上的冗余 API,移除是为了让 Vue 更简洁、更贴合原生 JavaScript。
核心原因有 5 点,每一点都直击痛点:
1. 语法非原生,破坏 JS 一致性
过滤器的管道符
| 是 Vue 自定义语法,不属于 JavaScript 标准。
模板里的表达式本该是纯 JS,但过滤器打破了这个规则,新手需要额外学习,增加了框架学习成本。
2. 功能完全冗余,无不可替代性
过滤器能做的事,计算属性(computed)和方法(methods)100% 能实现,甚至更灵活。
没有任何功能是过滤器独有,保留它只会让 API 体系更臃肿。
3. TypeScript 支持极差
大型项目主流使用 TS 开发,但过滤器无法做类型推断,输入输出类型难以约束,容易引发类型错误,不符合 Vue 3 拥抱 TS 的设计理念。
4. 性能与调试劣势
- 过滤器每次渲染都会执行,没有缓存机制,频繁渲染时性能不如计算属性;
- 全局过滤器分散定义,大型项目中难以追踪调用链路,调试成本高。
5. 与 Composition API 不兼容
Vue 3 的核心是 Composition API,而过滤器无法在
setup 中直接使用,只能通过复杂方式兼容,与新架构格格不入。综上,Vue 3 移除过滤器,不是 “砍功能”,而是做减法、优化架构,让框架更轻量化、更贴近原生 JS。
三、Vue 3 过滤器的官方替代方案
Vue 3 官方明确推荐:用计算属性、方法调用替代过滤器,全局过滤器则用全局属性或工具函数替代。
以下是分场景的实战方案,直接复制可用:
方案 1:计算属性(Computed)—— 无参格式化首选
适用场景:不需要传参、数据固定的格式化(如价格、日期固定格式)。
优势:自带缓存,依赖数据不变时不会重复执行,性能最优。
Options API 写法
vue
<template>
<div>{{ formattedPrice }}</div>
</template>
<script>
export default {
data() {
return {
price: 99.8
}
},
computed: {
// 替代过滤器
formattedPrice() {
if (!this.price) return '¥0.00'
return '¥' + this.price.toFixed(2)
}
}
}
</script>
Composition API(setup)写法
vue
<template>
<div>{{ formattedPrice }}</div>
</template>
<script setup>
import { ref, computed } from 'vue'
const price = ref(99.8)
// 计算属性替代过滤器
const formattedPrice = computed(() => {
if (!price.value) return '¥0.00'
return '¥' + price.value.toFixed(2)
})
</script>
方案 2:方法调用(Methods)—— 带参格式化首选
适用场景:需要传递参数、动态格式化(如自定义日期格式、多场景价格格式化)。
优势:灵活传参,用法和过滤器几乎一致,迁移成本最低。
vue
<template>
<!-- 直接调用方法,支持传参 -->
<div>{{ formatPrice(price) }}</div>
<div>{{ formatDate(createTime, 'YYYY-MM-DD HH:mm') }}</div>
</template>
<script setup>
import { ref } from 'vue'
import dayjs from 'dayjs'
const price = ref(99.8)
const createTime = ref(new Date())
// 方法替代过滤器
const formatPrice = (value) => {
if (!value) return '¥0.00'
return '¥' + value.toFixed(2)
}
// 带参方法替代过滤器
const formatDate = (value, format = 'YYYY-MM-DD') => {
if (!value) return ''
return dayjs(value).format(format)
}
</script>
方案 3:全局工具函数 —— 替代全局过滤器
适用场景:需要全项目复用的格式化逻辑(如全局日期、价格、手机号格式化)。
步骤 1:定义工具函数
javascript
运行
// src/utils/format.js
// 价格格式化
export const formatPrice = (value) => {
if (!value) return '¥0.00'
return '¥' + value.toFixed(2)
}
// 首字母大写
export const capitalize = (value) => {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
步骤 2:全局挂载(可选)
javascript
运行
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import * as filters from './utils/format'
const app = createApp(App)
// 全局挂载,替代Vue 2全局过滤器
app.config.globalProperties.$filters = filters
app.mount('#app')
步骤 3:组件中使用
vue
<template>
<div>{{ $filters.formatPrice(price) }}</div>
</template>
<script setup>
import { ref } from 'vue'
// 也可直接导入,更推荐TS项目使用
import { formatPrice } from '@/utils/format'
const price = ref(99.8)
</script>
方案 4:组合式函数(Composables)—— 复杂逻辑复用
适用场景:包含响应式数据的复杂格式化逻辑,跨组件复用。
javascript
运行
// src/composables/useFormat.js
import { computed } from 'vue'
// 封装价格格式化组合式函数
export function usePriceFormat(price) {
const formattedPrice = computed(() => {
if (!price.value) return '¥0.00'
return '¥' + price.value.toFixed(2)
})
return { formattedPrice }
}
组件中使用:
vue
<script setup>
import { ref } from 'vue'
import { usePriceFormat } from '@/composables/useFormat'
const price = ref(99.8)
const { formattedPrice } = usePriceFormat(price)
</script>
四、替代方案选型指南
表格
| 方案 | 适用场景 | 优势 | 推荐度 |
|---|---|---|---|
| 计算属性 | 无参、固定格式化 | 自带缓存,性能最优 | ⭐⭐⭐⭐⭐ |
| 方法调用 | 带参、动态格式化 | 灵活传参,迁移简单 | ⭐⭐⭐⭐⭐ |
| 全局工具函数 | 全项目复用格式化 | 统一管理,TS 友好 | ⭐⭐⭐⭐ |
| 组合式函数 | 复杂响应式格式化 | 适配 Composition API | ⭐⭐⭐⭐ |
总结:日常开发优先用计算属性 + 方法调用,全局复用用工具函数,复杂逻辑用组合式函数,完全覆盖过滤器所有场景。
五、写在最后
Vue 3 移除过滤器,是框架走向轻量化、原生化、工程化的重要一步。看似少了一个 API,实则让代码更规范、更易维护、更贴合 JavaScript 原生语法。
对于 Vue 2 迁移项目,不用纠结过滤器的缺失,按照本文的替代方案改造,代码会更简洁、性能更优;对于 Vue 3 新手,直接学习计算属性和方法,反而能少学一个冗余 API,更快上手 Vue 核心逻辑。
过滤器已成过去,原生 JS+Vue 官方 API才是未来。