过滤器使用

过滤器可以用在两个地方:双花括号插值和 v-bind 表达式中。过滤器使用方法详解,在插值和v-bind中使用过滤器。

在插值中使用

<div id="app">
  <p>{{ message | capitalize }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'hello vue'
  },
  filters: {
    capitalize(value) {
      if (!value) return ''
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})
</script>

在 v-bind 中使用

<div id="app">
  <div :title="message | uppercase">悬停查看</div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'hello vue'
  },
  filters: {
    uppercase(value) {
      return value ? value.toUpperCase() : ''
    }
  }
})
</script>

链式调用

过滤器可以串联使用,前一个过滤器的输出作为后一个的输入:

<div id="app">
  <p>{{ message | capitalize | reverse }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'hello'
  },
  filters: {
    capitalize(value) {
      if (!value) return ''
      return value.charAt(0).toUpperCase() + value.slice(1)
    },
    reverse(value) {
      if (!value) return ''
      return value.split('').reverse().join('')
    }
  }
})
</script>

输出:olleH

执行顺序:messagecapitalizereverse

在 v-for 中使用

<div id="app">
  <ul>
    <li v-for="item in items" :key="item.id">
      {{ item.name | uppercase }}
    </li>
  </ul>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    items: [
      { id: 1, name: 'apple' },
      { id: 2, name: 'banana' },
      { id: 3, name: 'orange' }
    ]
  },
  filters: {
    uppercase(value) {
      return value ? value.toUpperCase() : ''
    }
  }
})
</script>

在计算属性中使用

过滤器函数可以在计算属性中调用:

<div id="app">
  <p>{{ formattedMessage }}</p>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    message: 'hello vue'
  },
  computed: {
    formattedMessage() {
      return this.$options.filters.capitalize(this.message)
    }
  },
  filters: {
    capitalize(value) {
      if (!value) return ''
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
  }
})
</script>

在方法中使用

methods: {
  getFormattedValue(value) {
    return this.$options.filters.currency(value)
  }
}

在 JavaScript 中调用全局过滤器

Vue.filter('currency', function(value) {
  return '¥' + Number(value).toFixed(2)
})

new Vue({
  el: '#app',
  methods: {
    formatPrice(price) {
      return Vue.filter('currency')(price)
    }
  }
})

实际应用示例

格式化用户信息

<div id="app">
  <div class="user-card">
    <h3>{{ user.name | capitalize }}</h3>
    <p>{{ user.email | lowercase }}</p>
    <p>{{ user.bio | truncate:50 }}</p>
    <p>{{ user.createdAt | date:'YYYY-MM-DD' }}</p>
  </div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    user: {
      name: 'john doe',
      email: 'JOHN@EXAMPLE.COM',
      bio: '这是一个前端开发工程师,拥有多年开发经验,擅长Vue和React框架',
      createdAt: '2024-01-15T10:30:00'
    }
  },
  filters: {
    capitalize(value) {
      if (!value) return ''
      return value.charAt(0).toUpperCase() + value.slice(1)
    },
    lowercase(value) {
      return value ? value.toLowerCase() : ''
    },
    truncate(value, length = 20) {
      if (!value) return ''
      return value.length > length ? value.slice(0, length) + '...' : value
    },
    date(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')
      return format
        .replace('YYYY', year)
        .replace('MM', month)
        .replace('DD', day)
    }
  }
})
</script>

商品列表

<div id="app">
  <div class="product" v-for="product in products" :key="product.id">
    <h3>{{ product.name }}</h3>
    <p class="price">{{ product.price | currency }}</p>
    <p class="original" v-if="product.originalPrice">
      原价: {{ product.originalPrice | currency }}
    </p>
    <p class="discount" v-if="product.discount">
      {{ product.discount | discount }}
    </p>
  </div>
</div>

<script>
new Vue({
  el: '#app',
  data: {
    products: [
      { id: 1, name: '商品A', price: 99.9, originalPrice: 199.9, discount: 0.5 },
      { id: 2, name: '商品B', price: 199, discount: null },
      { id: 3, name: '商品C', price: 49.9, originalPrice: 99.9, discount: 0.5 }
    ]
  },
  filters: {
    currency(value) {
      return '¥' + Number(value).toFixed(2)
    },
    discount(value) {
      if (!value) return ''
      return (value * 10).toFixed(1) + '折'
    }
  }
})
</script>

过滤器使用限制

过滤器只能用于:

  • 双花括号插值 {{ }}
  • v-bind 表达式

过滤器不能用于:

  • v-model
  • v-on
  • v-if / v-show
  • 其他指令

最佳实践

  1. 简单转换用过滤器:如格式化、大小写转换
  2. 复杂逻辑用计算属性:涉及多个数据源或复杂计算
  3. 避免副作用:过滤器应该是纯函数
  4. 合理命名:过滤器名应描述转换效果