Vue.js 过滤器详解

发布于:2025-06-27 ⋅ 阅读:(17) ⋅ 点赞:(0)

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>

过滤器注意事项

  1. 过滤器只用于文本转换:适用于简单的文本格式化,不应用于复杂的数据转换
  2. 参数传递
    • 第一个参数始终是管道前的值
    • 后续参数是调用时传入的参数
  3. 链式调用顺序:从左到右执行,前一个过滤器的结果作为后一个过滤器的输入
  4. 返回值:过滤器必须返回一个值
  5. Vue 3的变化:Vue 3中移除了过滤器,官方推荐使用方法或计算属性替代
  6. 性能考虑:避免在过滤器中执行复杂操作,特别是大数据量时
  7. 作用域:过滤器函数内无法访问组件实例(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>

关键知识点总结

  1. 过滤器定义

    • 全局过滤器使用Vue.filter()定义
    • 局部过滤器在组件选项的filters属性中定义
  2. 过滤器使用

    • 通过管道符 | 使用
    • 可以链式调用:{{ value | filterA | filterB }}
    • 可以传递参数:{{ value | filter(arg1, arg2) }}
  3. 过滤器特点

    • 第一个参数是管道符前的值
    • 必须返回一个值
    • 不改变原始数据,只做格式化展示
    • 不能访问组件实例(this为undefined)
  4. Vue 3的变更

    • Vue 3中已移除过滤器
    • 替代方案:使用计算属性或方法
    • 示例:{{ formatCurrency(price) }}
  5. 最佳实践

    • 用于简单文本格式化
    • 复杂逻辑使用计算属性
    • 保持过滤器函数纯净(无副作用)
    • 考虑向后兼容性(Vue 3迁移)

这个演示页面展示了Vue 2中过滤器的各种用法,同时提供了Vue 3的迁移建议,帮助开发者更好地理解和应用过滤器功能。


网站公告

今日签到

点亮在社区的每一天
去签到