Vue 过滤器详解
1. 过滤器基础概念
Vue 过滤器主要用于文本格式化,可以在模板中直接使用。注意:Vue 3 已移除过滤器,但在 Vue 2 中仍然常用。
基本语法
<template>
<!-- 使用过滤器 -->
<div>{{ message | capitalize }}</div>
<!-- 链式调用 -->
<div>{{ price | currency | uppercase }}</div>
<!-- 带参数的过滤器 -->
<div>{{ date | formatDate('YYYY-MM-DD') }}</div>
</template>
2. 过滤器的定义方式
全局过滤器
// main.js
Vue.filter('capitalize', function(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
Vue.filter('currency', function(value, symbol = '$') {
return symbol + Number(value).toFixed(2)
})
局部过滤器
export default {
filters: {
capitalize(value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
},
truncate(value, length = 10) {
if (!value) return ''
if (value.length <= length) return value
return value.substring(0, length) + '...'
}
}
}
3. 常见应用场景
文本格式化
// 首字母大写
filters: {
capitalize(value) {
if (!value) return ''
return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase()
}
}
// 在模板中使用
// {{ 'hello world' | capitalize }} → "Hello world"
金额格式化
filters: {
currency(value, symbol = '¥', decimals = 2) {
const numericValue = parseFloat(value)
if (isNaN(numericValue)) return symbol + '0.00'
return symbol + numericValue.toFixed(decimals).replace(/\d(?=(\d{3})+\.)/g, '$&,')
}
}
// 使用:{{ 1234.56 | currency }} → "¥1,234.56"
// 使用:{{ 1234.56 | currency('$') }} → "$1,234.56"
日期格式化
filters: {
formatDate(value, format = 'YYYY-MM-DD') {
if (!value) return ''
const date = new Date(value)
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
const hours = String(date.getHours()).padStart(2, '0')
const minutes = String(date.getMinutes()).padStart(2, '0')
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day)
.replace('HH', hours)
.replace('mm', minutes)
}
}
// 使用:{{ new Date() | formatDate }} → "2024-01-15"
// 使用:{{ new Date() | formatDate('YYYY/MM/DD HH:mm') }} → "2024/01/15 14:30"
文件大小格式化
filters: {
fileSize(bytes) {
if (bytes === 0) return '0 Bytes'
const k = 1024
const sizes = ['Bytes', 'KB', 'MB', 'GB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}
}
// 使用:{{ 1048576 | fileSize }} → "1 MB"
状态文本转换
filters: {
statusText(value) {
const statusMap = {
'0': '待处理',
'1': '处理中',
'2': '已完成',
'3': '已取消'
}
return statusMap[value] || '未知状态'
}
}
// 使用:{{ '1' | statusText }} → "处理中"
手机号脱敏
filters: {
phoneMask(value) {
if (!value) return ''
return value.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
}
}
// 使用:{{ '13812345678' | phoneMask }} → "138****5678"
HTML 内容处理
filters: {
stripTags(value) {
if (!value) return ''
return value.replace(/<[^>]*>/g, '')
}
}
// 使用:{{ '<p>Hello World</p>' | stripTags }} → "Hello World"
4. 在 methods 和 computed 中使用过滤器
export default {
data() {
return {
price: 99.9
}
},
filters: {
currency(value) {
return '¥' + Number(value).toFixed(2)
}
},
computed: {
// 在 computed 中使用过滤器逻辑
formattedPrice() {
return this.$options.filters.currency(this.price)
}
},
methods: {
// 在 methods 中使用过滤器逻辑
formatPrice(price) {
return this.$options.filters.currency(price)
}
}
}
5. Vue 3 中的替代方案
由于 Vue 3 移除了过滤器,可以采用以下替代方案:
使用 methods
export default {
methods: {
capitalize(value) {
if (!value) return ''
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
}
// 在模板中使用:{{ capitalize('hello') }}
使用 computed
export default {
data() {
return {
message: 'hello world'
}
},
computed: {
capitalizedMessage() {
return this.message.charAt(0).toUpperCase() + this.message.slice(1)
}
}
}
// 在模板中直接使用:{{ capitalizedMessage }}
使用全局方法
// 创建工具函数
const filters = {
currency(value) {
return '¥' + Number(value).toFixed(2)
}
}
// 注册为全局属性
app.config.globalProperties.$filters = filters
// 在组件中使用
export default {
mounted() {
console.log(this.$filters.currency(100))
}
}
6. 过滤器的优缺点
优点
- 声明式:在模板中直接使用,代码简洁
- 可复用:一次定义,多处使用
- 可组合:支持链式调用
- 职责分离:将数据转换逻辑从业务逻辑中分离
缺点
- 调试困难:在模板中调试不如在 JavaScript 中方便
- 性能开销:频繁调用可能影响性能
- Vue 3 不支持:需要迁移到其他方案
7. 最佳实践
- 保持纯净:过滤器应该是纯函数,不修改原始数据
- 处理边界情况:始终处理 null、undefined 等边界值
- 命名清晰:使用清晰的命名表明过滤器用途
- 避免复杂逻辑:复杂的转换逻辑建议放在 computed 或 methods 中
- 考虑性能:对于大数据量的处理,考虑使用 computed 缓存结果
虽然 Vue 3 已经移除了过滤器,但在 Vue 2 项目中,合理使用过滤器可以显著提高代码的可读性和可维护性。在 Vue 3 中,可以采用方法调用或计算属性来实现相同的功能。
THE END