过滤器参数

过滤器可以接收参数,第一个参数是管道符前的值,后续参数是传入的参数。

基本参数

<div id="app">
  <p>{{ message | truncate(10) }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: '这是一段很长的文字需要截断'
  },
  filters: {
    truncate(value, length) {
      if (!value) return ''
      return value.length > length ? value.slice(0, length) + '...' : value
    }
  }
})
</script>

输出:这是一段很长的文...

多个参数

<div id="app">
  <p>{{ price | currency('¥', 2) }}</p>
  <p>{{ price | currency('$', 3) }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    price: 99.956
  },
  filters: {
    currency(value, symbol, decimals) {
      return symbol + Number(value).toFixed(decimals)
    }
  }
})
</script>

输出:

¥99.96
$99.956

默认参数

filters: {
  currency(value, symbol = '¥', decimals = 2) {
    return symbol + Number(value).toFixed(decimals)
  },
  
  truncate(value, length = 20, suffix = '...') {
    if (!value) return ''
    return value.length > length ? value.slice(0, length) + suffix : value
  }
}

使用:

<p>{{ price | currency }}</p>
<p>{{ price | currency('$') }}</p>
<p>{{ price | currency('€', 3) }}</p>

<p>{{ text | truncate }}</p>
<p>{{ text | truncate(10) }}</p>
<p>{{ text | truncate(10, '…') }}</p>

动态参数

参数可以是数据属性:

<div id="app">
  <p>{{ price | currency(symbol, decimals) }}</p>
  
  <select v-model="symbol">
    <option value="¥">人民币</option>
    <option value="$">美元</option>
    <option value="€">欧元</option>
  </select>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    price: 99.95,
    symbol: '¥',
    decimals: 2
  },
  filters: {
    currency(value, symbol, decimals) {
      return symbol + Number(value).toFixed(decimals)
    }
  }
})
</script>

链式调用传参

每个过滤器可以有独立的参数:

<div id="app">
  <p>{{ message | truncate(10) | uppercase }}</p>
  <p>{{ price | currency('¥') | addSuffix('元') }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'hello world',
    price: 99.9
  },
  filters: {
    truncate(value, length) {
      if (!value) return ''
      return value.length > length ? value.slice(0, length) + '...' : value
    },
    uppercase(value) {
      return value ? value.toUpperCase() : ''
    },
    currency(value, symbol) {
      return symbol + Number(value).toFixed(2)
    },
    addSuffix(value, suffix) {
      return value + suffix
    }
  }
})
</script>

输出:

HELLO WORL...
¥99.90元

日期格式化参数

<div id="app">
  <p>{{ date | formatDate('YYYY-MM-DD') }}</p>
  <p>{{ date | formatDate('YYYY年MM月DD日') }}</p>
  <p>{{ date | formatDate('MM/DD/YYYY') }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    date: new Date()
  },
  filters: {
    formatDate(value, format = 'YYYY-MM-DD') {
      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')
      const seconds = String(date.getSeconds()).padStart(2, '0')
      
      return format
        .replace('YYYY', year)
        .replace('MM', month)
        .replace('DD', day)
        .replace('HH', hours)
        .replace('mm', minutes)
        .replace('ss', seconds)
    }
  }
})
</script>

数组/对象参数

传递复杂参数:

<div id="app">
  <p>{{ user | formatUser({ showEmail: true }) }}</p>
  <p>{{ user | formatUser({ showEmail: false }) }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    user: {
      name: 'John',
      email: 'john@example.com'
    }
  },
  filters: {
    formatUser(user, options = {}) {
      let result = user.name
      if (options.showEmail) {
        result += ` (${user.email})`
      }
      return result
    }
  }
})
</script>

完整示例

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
  <style>
    .product { border: 1px solid #ddd; padding: 15px; margin: 10px 0; }
    .price { color: #e74c3c; font-size: 24px; }
    .original { text-decoration: line-through; color: #999; }
  </style>
</head>
<body>
  <div id="app">
    <div class="product" v-for="product in products" :key="product.id">
      <h3>{{ product.name }}</h3>
      <p class="price">{{ product.price | currency(currencySymbol, 2) }}</p>
      <p class="original" v-if="product.originalPrice">
        原价: {{ product.originalPrice | currency(currencySymbol, 2) }}
      </p>
      <p>{{ product.description | truncate(50, '…') }}</p>
      <p>上架: {{ product.createdAt | formatDate('YYYY-MM-DD HH:mm') }}</p>
    </div>
    
    <div>
      <label>货币符号:</label>
      <select v-model="currencySymbol">
        <option value="¥">人民币 ¥</option>
        <option value="$">美元 $</option>
        <option value="€">欧元 €</option>
      </select>
    </div>
  </div>

  <script>
    new Vue({
      el: '#app',
      data: {
        currencySymbol: '¥',
        products: [
          {
            id: 1,
            name: 'Vue.js 实战教程',
            price: 99.9,
            originalPrice: 199.9,
            description: '这是一套完整的Vue.js教程,从入门到精通,包含大量实战案例',
            createdAt: '2024-01-15T10:30:00'
          },
          {
            id: 2,
            name: 'React 进阶指南',
            price: 149,
            originalPrice: null,
            description: '深入学习React的高级特性和最佳实践',
            createdAt: '2024-02-20T14:00:00'
          }
        ]
      },
      filters: {
        currency(value, symbol = '¥', decimals = 2) {
          return symbol + Number(value).toFixed(decimals)
        },
        
        truncate(value, length = 20, suffix = '...') {
          if (!value) return ''
          return value.length > length ? value.slice(0, length) + suffix : value
        },
        
        formatDate(value, format = 'YYYY-MM-DD') {
          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)
        }
      }
    })
  </script>
</body>
</html>

参数传递规则

{{ value | filter(arg1, arg2) }}

等价于:

filter(value, arg1, arg2)
  • 第一个参数是管道符前的值
  • 后续参数是括号中传入的值