Vue.js 过滤器详解
下面我将详细讲解Vue.js中过滤器的语法和使用注意事项,并提供一个完整的演示页面。
过滤器基本概念
在Vue.js中,过滤器(Filters) 是用于文本格式化的功能,可以在双花括号插值和v-bind
表达式中使用。过滤器通过管道符(|)指示,主要用于简单的文本转换。
<!-- 基本语法 -->
{{ message | capitalize }}
<!-- 链式调用 -->
{{ message | filterA | filterB }}
<!-- 带参数的过滤器 -->
{{ date | formatDate('YYYY-MM-DD') }}
过滤器语法详解
1. 全局过滤器定义
Vue.filter('filterName', function(value, ...args) {
// 处理逻辑
return transformedValue;
});
2. 局部过滤器定义
new Vue({
filters: {
filterName(value, ...args) {
// 处理逻辑
return transformedValue;
}
}
});
3. 使用方式
<!-- 在插值中使用 -->
<p>{{ price | currency }}</p>
<!-- 在v-bind中使用 -->
<div v-bind:id="rawId | formatId"></div>
<!-- 链式调用 -->
<p>{{ text | trim | capitalize }}</p>
<!-- 带参数 -->
<p>{{ now | dateFormat('YYYY年MM月DD日') }}</p>
过滤器注意事项
- 过滤器只用于文本转换:适用于简单的文本格式化,不应用于复杂的数据转换
- 参数传递:
- 第一个参数始终是管道前的值
- 后续参数是调用时传入的参数
- 链式调用顺序:从左到右执行,前一个过滤器的结果作为后一个过滤器的输入
- 返回值:过滤器必须返回一个值
- Vue 3的变化:Vue 3中移除了过滤器,官方推荐使用方法或计算属性替代
- 性能考虑:避免在过滤器中执行复杂操作,特别是大数据量时
- 作用域:过滤器函数内无法访问组件实例(this为undefined)
完整演示示例
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue.js 过滤器详解</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
body {
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
min-height: 100vh;
padding: 20px;
color: #333;
}
.container {
max-width: 1000px;
margin: 40px auto;
background: rgba(255, 255, 255, 0.95);
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
overflow: hidden;
}
header {
background: linear-gradient(90deg, #3498db, #2c3e50);
color: white;
padding: 30px 40px;
text-align: center;
}
h1 {
font-size: 2.5rem;
margin-bottom: 10px;
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
.subtitle {
font-size: 1.2rem;
opacity: 0.9;
max-width: 700px;
margin: 0 auto;
}
.content {
display: flex;
flex-wrap: wrap;
padding: 30px;
}
.panel {
flex: 1;
min-width: 300px;
padding: 25px;
margin: 15px;
background: white;
border-radius: 10px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
transition: transform 0.3s ease;
}
.panel:hover {
transform: translateY(-5px);
}
.panel h2 {
color: #2c3e50;
border-bottom: 2px solid #3498db;
padding-bottom: 10px;
margin-bottom: 20px;
display: flex;
align-items: center;
}
.panel h2 i {
margin-right: 10px;
color: #3498db;
}
.example {
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
margin: 15px 0;
border-left: 4px solid #3498db;
}
.input-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #2c3e50;
}
input, select, textarea {
width: 100%;
padding: 12px 15px;
border: 1px solid #ddd;
border-radius: 6px;
font-size: 16px;
transition: border 0.3s;
}
input:focus, select:focus, textarea:focus {
outline: none;
border-color: #3498db;
box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
}
.result {
background: #e3f2fd;
padding: 15px;
border-radius: 8px;
margin-top: 15px;
min-height: 50px;
font-size: 18px;
font-weight: 500;
color: #0d47a1;
}
.note {
background: #fff8e1;
border-left: 4px solid #ffc107;
padding: 15px;
margin-top: 20px;
border-radius: 0 8px 8px 0;
}
.note h3 {
color: #ff9800;
margin-bottom: 10px;
}
.code {
background: #2c3e50;
color: #ecf0f1;
padding: 20px;
border-radius: 8px;
font-family: 'Courier New', monospace;
margin: 15px 0;
overflow-x: auto;
}
.footer {
text-align: center;
padding: 20px;
background: #f8f9fa;
color: #6c757d;
font-size: 0.9rem;
border-top: 1px solid #eee;
}
.filters-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
margin-top: 20px;
}
.filter-item {
background: #e3f2fd;
padding: 15px;
border-radius: 8px;
border-left: 4px solid #2196f3;
}
.filter-item h4 {
margin-bottom: 8px;
color: #0d47a1;
}
@media (max-width: 768px) {
.content {
flex-direction: column;
}
.panel {
min-width: 100%;
margin: 10px 0;
}
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<header>
<h1>Vue.js 过滤器详解</h1>
<p class="subtitle">过滤器用于文本格式化,在Vue 2中通过管道符(|)使用。Vue 3中已移除,建议使用计算属性或方法替代。</p>
</header>
<div class="content">
<div class="panel">
<h2><i class="fas fa-filter"></i> 过滤器演示</h2>
<div class="input-group">
<label for="textInput">输入文本:</label>
<input type="text" id="textInput" v-model="inputText" placeholder="输入文本进行格式化">
</div>
<div class="input-group">
<label for="numberInput">输入数值:</label>
<input type="number" id="numberInput" v-model.number="inputNumber" placeholder="输入数值进行格式化">
</div>
<div class="filters-list">
<div class="filter-item">
<h4>大写转换</h4>
<div class="result">{{ inputText | uppercase }}</div>
</div>
<div class="filter-item">
<h4>首字母大写</h4>
<div class="result">{{ inputText | capitalize }}</div>
</div>
<div class="filter-item">
<h4>货币格式化</h4>
<div class="result">{{ inputNumber | currency }}</div>
</div>
<div class="filter-item">
<h4>百分比</h4>
<div class="result">{{ inputNumber | percent }}</div>
</div>
<div class="filter-item">
<h4>反转文本</h4>
<div class="result">{{ inputText | reverse }}</div>
</div>
<div class="filter-item">
<h4>截断文本</h4>
<div class="result">{{ inputText | truncate(20) }}</div>
</div>
<div class="filter-item">
<h4>日期格式化</h4>
<div class="result">{{ currentDate | dateFormat('YYYY年MM月DD日') }}</div>
</div>
<div class="filter-item">
<h4>链式调用</h4>
<div class="result">{{ inputText | uppercase | truncate(15) }}</div>
</div>
</div>
</div>
<div class="panel">
<h2><i class="fas fa-code"></i> 过滤器定义</h2>
<div class="example">
<h3>全局过滤器</h3>
<div class="code">
// 大写转换过滤器
Vue.filter('uppercase', function(value) {
if (!value) return '';
return value.toString().toUpperCase();
});
// 货币格式化过滤器
Vue.filter('currency', function(value) {
if (value === null || value === undefined) return '';
return '¥' + value.toFixed(2);
});
</div>
</div>
<div class="example">
<h3>局部过滤器</h3>
<div class="code">
new Vue({
filters: {
// 首字母大写
capitalize: function(value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
},
// 带参数的截断过滤器
truncate: function(value, length) {
if (!value) return '';
if (value.length <= length) return value;
return value.substring(0, length) + '...';
}
}
});
</div>
</div>
<div class="example">
<h3>带参数的过滤器</h3>
<div class="code">
// 日期格式化过滤器
Vue.filter('dateFormat', function(value, format) {
if (!value) return '';
const date = new Date(value);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day);
});
</div>
</div>
<div class="note">
<h3><i class="fas fa-exclamation-triangle"></i> 重要注意事项</h3>
<ul>
<li>过滤器只用于文本格式化,不改变原始数据</li>
<li>过滤器函数应保持纯净,不产生副作用</li>
<li>过滤器不能访问组件实例(this为undefined)</li>
<li>Vue 3中已移除过滤器功能,建议使用方法或计算属性替代</li>
<li>复杂逻辑应使用计算属性而非过滤器</li>
<li>过滤器可以链式调用,顺序从左到右</li>
<li>第一个参数始终是管道符前的值</li>
</ul>
</div>
</div>
</div>
<div class="footer">
<p>Vue.js 过滤器演示 | 在实际项目中考虑Vue版本兼容性</p>
</div>
</div>
</div>
<script>
// 全局过滤器定义
Vue.filter('uppercase', function(value) {
if (!value) return '';
return value.toString().toUpperCase();
});
Vue.filter('reverse', function(value) {
if (!value) return '';
return value.toString().split('').reverse().join('');
});
Vue.filter('currency', function(value) {
if (value === null || value === undefined) return '';
return '¥' + value.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,');
});
Vue.filter('percent', function(value) {
if (value === null || value === undefined) return '';
return (value * 100).toFixed(2) + '%';
});
Vue.filter('dateFormat', function(value, format) {
if (!value) return '';
const date = new Date(value);
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, '0');
const day = date.getDate().toString().padStart(2, '0');
return format
.replace('YYYY', year)
.replace('MM', month)
.replace('DD', day);
});
new Vue({
el: '#app',
data: {
inputText: 'Vue过滤器使用示例',
inputNumber: 1234.567,
currentDate: new Date()
},
filters: {
// 局部过滤器:首字母大写
capitalize: function(value) {
if (!value) return '';
value = value.toString();
return value.charAt(0).toUpperCase() + value.slice(1);
},
// 局部过滤器:截断文本
truncate: function(value, length) {
if (!value) return '';
if (value.length <= length) return value;
return value.substring(0, length) + '...';
}
}
});
</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
</body>
</html>
关键知识点总结
过滤器定义:
- 全局过滤器使用
Vue.filter()
定义 - 局部过滤器在组件选项的
filters
属性中定义
- 全局过滤器使用
过滤器使用:
- 通过管道符
|
使用 - 可以链式调用:
{{ value | filterA | filterB }}
- 可以传递参数:
{{ value | filter(arg1, arg2) }}
- 通过管道符
过滤器特点:
- 第一个参数是管道符前的值
- 必须返回一个值
- 不改变原始数据,只做格式化展示
- 不能访问组件实例(this为undefined)
Vue 3的变更:
- Vue 3中已移除过滤器
- 替代方案:使用计算属性或方法
- 示例:
{{ formatCurrency(price) }}
最佳实践:
- 用于简单文本格式化
- 复杂逻辑使用计算属性
- 保持过滤器函数纯净(无副作用)
- 考虑向后兼容性(Vue 3迁移)
这个演示页面展示了Vue 2中过滤器的各种用法,同时提供了Vue 3的迁移建议,帮助开发者更好地理解和应用过滤器功能。