平時開發中,需要用到過濾器的地方有很多,比如單位轉換、金額加千分位、文本格式化等,比如:
1 // 格式化金額 2 const digitsRE = /(\d{3})(?=\d)/g 3 Vue.filter('currencyFilter', function (value) { 4 value = parseFloat(value) 5 if (!isFinite(value) || (!value && value !== 0)) return '' 6 currency = currency != null ? currency : '$' 7 decimals = decimals != null ? decimals : 2 8 var stringified = Math.abs(value).toFixed(decimals) 9 var _int = decimals ? stringified.slice(0, -1 - decimals) : stringified 12 var i = _int.length % 3 13 var head = i > 0 ? (_int.slice(0, i) + (_int.length > 3 ? ',' : '')) : '' 16 var _float = decimals ? stringified.slice(-1 - decimals) : '' 19 var sign = value < 0 ? '-' : '' 20 return sign + currency + head + _int.slice(i).replace(digitsRE, '$1,') + _float 23 })
實現效果16568686.00=> 16,568,686.00
這是常規用法,沒什么好說的。下面來說一下在開發中遇到的一個需要用到串聯過濾器的使用場景。
假設需要獲取一個訂單處理狀態的列表,其中的每一項的 status 字段用來表示訂單狀態:
1 { 2 id: '', 3 order_num: '123456789', 4 goodList: [ ... ], 5 address: { ... }, 6 status: 1 // 1 待支付 2 待發貨 3 待收貨 7 }
當我們拿到這個數據之后,v-for 的時候,肯定會這樣做:
1 <template> 2 <!-- ... --> 3 <span class="order_status_wrap">{{ orderItem.status | getOrderStatus }}</span> 4 <!-- ... --> 5 </template> 6 <script> 7 export default { 8 // ... 9 filters: { 10 getOrderStatus(status) { 11 switch (status.toString()) { 12 case '1': 13 return '待支付'; 14 case '2': 15 return '待發貨'; 16 case '3': 17 return '待收貨'; 18 default: 19 return ''; 20 } 21 } 22 } 23 // ... 24 } 25 </script> 26 <style scoped type="scss"> 27 // ... 28 .order_status_wrap { 29 font-size: 14px; 30 } 31 // ... 32 </style>
這樣,表示狀態的 1, 2, 3 就變成了 待支付,待發貨,待收貨,這沒有什么問題。但是,當需求來了,要求當狀態是待支付時,文字應該為紅色。
vue文檔中有寫串聯過濾器的用法,針對這個問題可以很好的解決。
1 <template> 2 <!-- ... --> 3 <span class="order_status" :class="orderItem.status | getOrderStatus | getOrderStatusClass">{{ orderItem.status | getOrderStatus }}</span> 4 <!-- ... --> 5 </template> 6 <script> 7 export default { 8 // ... 9 filters: { 10 getOrderStatus(status) { 11 switch (status.toString()) { 12 case '1': 13 return '待支付'; 14 case '2': 15 return '待發貨'; 16 case '3': 17 return '待收貨'; 18 default: 19 return ''; 20 } 21 }, 22 getOrderStatusClass(status) { 23 if (status === '待支付') { 24 return 'not-pay' 25 } 26 return '' 27 } 28 } 29 // ... 30 } 31 </script> 32 <style scoped type="scss"> 33 // ... 34 .order_status { 35 font-size: 14px; 36 &.not-pay { 37 color: red; 38 } 39 } 40 // ... 41 </style>
關於過濾器,這里還有幾點要注意的:
- 過濾器必須是個純函數
- 過濾器中拿不到 vue 實例,這是 vue 故意這么做的
- 在全局注冊過濾器是用 Vue.filter(),局部則是 filters: {}
- 在方法中調用過濾器方法為: this.$http://options.filters.XXX