iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 29
0
Modern Web

實作小範例入門 Vue & Vuex 2.0系列 第 29

vue & vuex 29 - custom Filter (currency、Letter Grade、GPA、lowercase)

今天動手來實作過濾器 Filter 通常用來 format model 的格式,功能上有點類似 computed 因此我們可以利用 Filter 制定系統中常用的 format

vue & vuex 29 - custom Filter (currency、Letter Grade、GPA、lowercase)

vue & vuex 29 - custom Filter (currency、Letter Grade、GPA、lowercase)

今天目標:

  1. shop 與 cart Page 價錢的部分,希望可以顯示成貨幣的格式。
  2. 顯示一份成績單需要有原始分數、Letter Grade、GPA 分數。
  3. 有時候希望不動原始資料的情況,讓畫面上的文字以小寫顯示。

Filter 起手式,幫它命名

import Vue 並使用 filter 來設計,

參數一 參數二
filter name function
import Vue from 'vue';

Vue.filter('filterName', function(value) {
  //custom format
  return value.do.some.
});

在 temaplet 上使用:

使用的時候在 bind 的 model 後面使用加上 | 之後再放上 filter name

<p>{{ data | filterName }}</p>

在顯示之前,會透過 filter 過濾格式。


filter example

import Vue from 'vue';

Vue.filter('currency', function (num) {
  return '$ ' + num.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, "$1, ");
});

Vue.filter('lowercase', (str) => str.toLowerCase() );

// Letter Grade & GPA
function letterGrade (score) {
  if (score > 100 || score < 0) {
    return '--';
  }
  else if (score >= 90) {
    return 'A';
  }
  else if (score >= 80) {
    return 'B';
  }
  else if (score >= 70) {
    return 'C';
  }
  else if (score >= 60) {
    return 'D';
  }
  else {
    return 'F';
  }
}

Vue.filter('letterGrade', letterGrade);

Vue.filter('gpa', (score) => {
  const _score = letterGrade(score);
  const gpa = {
    A: '4.0',
    B: '3.0',
    C: '2.0',
    D: '1.0',
    F: '0.0',
  }
  return gpa[ _score ] || _score;
});

demoFilter.vue

<template>
  <div class="container">
    <h1>Vue Filter</h1>
    <hr>
    <div class="row">
      <div class="col-md-4">
        <h2>currency:</h2>
        <input type="number" v-model="demoCurrency" />
        <h3>{{ demoCurrency | currency}}</h3> <!-- 過濾貨幣 -->
      </div>
      <div class="col-md-4">
        <h2>lowercase:</h2>
        <input type="text" v-model="demoLowerCase" />
        <h3>{{ demoLowerCase | lowercase}}</h3> <!-- 過濾小寫 -->
      </div>
      <div class="col-md-4">
        <h2>Letter Grade:</h2>
        <input type="number" v-model="demoScore" />
        <h3>{{ demoScore | letterGrade}}
          <small>GPA: ( {{ demoScore | gpa }} )</small><!-- 過濾 GPA -->
        </h3> <!-- 過濾 Letter Grade -->
      </div>
    </div>
   
    <hr>

    <h3>學期分數:</h3>
    <table class="table">
      <thead>
        <tr>
          <th>name</th>
          <th>Letter Grade</th>
          <th>score</th>
          <th>GPA</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in scoreList">
          <td>{{ item.name }}</td>
          <td>{{ item.score | letterGrade}}</td><!-- 過濾 Letter Grade -->
          <td>{{ item.score }}</td>
          <td>{{ item.score | gpa}}</td><!-- 過濾 GPA -->
        </tr>
      </tbody>
    </table>
  </div>
</template>

<script>
export default {
  data() {
    return {
      demoCurrency: 1000,
      demoLowerCase: 'LOWER CASE',
      demoScore: 99,
      scoreList: [
        {name: 'jacky', score: 100},
        {name: 'momo', score: 90},
        {name: 'jasper', score: 89},
        {name: 'eason', score: 80},
        {name: 'mars', score: 79},
        {name: 'mike', score: 70},
        {name: 'ben', score: 69},
        {name: 'Aaron', score: 60},
        {name: 'mary', score: 59},
      ],
    };
  },
};
</script>

關於 filter

在 Vue 1.x 的時候其實官方有制定許多個 filter 供開發者使用,

到了 Vue 2.x 官方移除了這些 filter 種種原因在這篇討論中:

[Suggestion] Vue 2.0 - Bring back filters please #2756

節錄幾個討論原因:

  1. 使用上不直覺
  2. 導致效能變差
  3. 使用者容易設計出不意閱讀的程式
    • 像 angular 時代串了一堆 filter..
    • ex {{ data | filter1:data2 | filter2 | filter3 | WTF }}
  4. 不容易 debug
  5. 你應該使用 computed
  6. 你應該使用 extend 收集這些 filter format function 然後注入到需要用的 component

angular 時代真的很容易也很愛開發那種 filter..
後面維護的同事看了表示香菇..

debug 看過.. 改一個 model 然後 filter 算了 30000 次..

實際使用

看完了 filter 的優缺點,目前使用上不多,

大部分都是像範例上這種簡單,不複雜計算的格式轉換,

這些格式轉換往往是需求的關係,所以在最後顯示之前過濾成需求的格式既可。

不會動到後端原始資料,設定的時候也不需要轉回原本格式,相當方便。

另外就是因為使用了 vuex 在有些狀況可以寫好 format function 如範例中: letterGrade

我們在 getter 的時候.. 先經過 letterGrade 過濾在把資料回傳,

因此 UI 就不用煩惱要在哪個流程 format,取得資料的時候就過濾好囉。

filter, getter 共用一個函式統一維護。

reference:


github 完整範例:

實作小範例入門 Vue & Vuex 2.0 - github 完整範例

使用 git checkout 切換每天範例。


上一篇
vue & vuex 28 - custom Directive (toggle password)
下一篇
vue & vuex 30 - 網站系統國際化 - 多語系(i18n)與持續學習相關資源
系列文
實作小範例入門 Vue & Vuex 2.030

尚未有邦友留言

立即登入留言