iT邦幫忙

1

前端金三角 (2):Pinia 智慧管家 —— 讓你的數據不再流離失所

  • 分享至 

  • xImage
  •  

什麼是 Vuex Store?

Vuex 的目的,就是讓整個專案的資料管理變得:集中、可控、可預測、同步、好維護。

  • 不可能每個元件、跨頁面各自打同一支 api ⇒ 共用api回傳的資料,用 Vuex 把資料存起來,也不用多層 props 傳遞

Vuex store 檔案彼此關係

  • state.js:唯一真實資料源
  • getter.js:把 state 派生成「計算後」的取用介面(類似 computed)
  • mutation.js同步修改 state 的唯一入口(只能同步)
  • action.js:放商業邏輯/非同步流程(打 API:get/post/patch/delete),完成後 commit mutation
  • index.js:把上面組起來(也可註冊 modules)

過去使用 Axios 和 Vuex store 來處理資料

  1. src/api/index.js 新增一個模組

    import activity from './activity';
    
    export default {
      activity,
    }
    
  2. src/api/activity.js 建立 api router

    import {axiosInstance} from 'boot/axios';
    
    const activityRouter = '/activities';
    
    export default {
      // 新增活動
      **addActivity**: (data) => axiosInstance.post(activityRouter, data),
    }
    
  3. src/store/index.js 新增一個模組,組合 state. getter. mutation. action

    import {store} from 'quasar/wrappers';
    import {createStore} from 'vuex';
    
    import Activity from './activity';
    
    export default store(function(/* { ssrContext } */) {
      const Store = createStore({
        modules: {
          Activity,
    		},
    	});
    
    	return Store;
    });
    
  4. src/store/activity/actions.js 打 api 的地方

    import api from 'src/api/index';
    
    export default {
    	// get: 取得活動列表
      async getActivities({commit}) {
        try {
          const res = await api.activity.getActivities();
          const data = res && res.activityList ? res.activityList : res;
          if (res && res.activityList) {
            **commit('setActivityList', data);  // 透過 commit 存入 Vuex State**
          }
          return data;
        } catch (err) {
          return err;
        }
      },
    
    	// post: 新增活動
      async addActivity({}, reqData) {
        try {
          const res = await api.activity.addActivity(reqData);
          return res;
        } catch (err) {
          return err;
        }
      },
    
      // patch: 編輯活動
      // **因為 action 只能收一個參數,所以我們把多個值包成一個 reqData 再在這裡解構**
      async updateActivity({}, reqData) {
        try {
          const {activityId, payload} = reqData;
          const res = await api.activity.updateActivity(activityId, payload);
          return res;
        } catch (err) {
          return err;
        }
      },
    
      // delete: 批次刪除
      async delete({}, payload) {
        try {
          const res = await api.elders.delete(payload);
          return res;
        } catch (err) {
          return err;
        }
      },
    
    }
    

    Vuex action 只能接收「一個 payload 參數」

    action(context, payload)
    
    • 第一個參數永遠是 context 物件(包含 commit、dispatch、state …),所以需要解構傳入
    • 第二個參數永遠只有一個 → 就是你傳進來的 payload,所以需要解構傳入 api router 中
  5. 會在 src/store/activity/mutations.js 中取到 commit 的內容,並存在 state 中

    export default {
      **setActivityList**(state, data) {
        **state.activityList** = data;
      },
    }
    
  6. src/store/activity/state.js 存放的地方

    export default {
      activityList: [],
      activities: [
        { id: 1, title: 'A', isActive: true },
        { id: 2, title: 'B', isActive: false },
        { id: 3, title: 'C', isActive: true }
      ]
    }
    
  7. src/store/activity/getter.js 把 state 的資料「整理成更方便使用的形式」,讓元件直接拿來用 computed,不用自己計算

    export default {
    	activeActivities: (state) => state.activities.filter(a => a.isActive)
    };
    
  8. 在該檔案下呼叫

    // 利用 store 儲存的 state 取資料
    const activityList = computed(() => store.state.Activity.activityList);
    
    // 打api
    try {
      const res = await store.dispatch('Activity/addActivity', { activity: payload });
      const { type } = handleNotifyInfo(res, '新增');
    
      if (type === 'positive') {
    	  // 新增成功後的後續處理
      }
    } catch (err) {
      // 這裡可以加錯誤通知
      triggerCustomNotify('warning', '新增活動發生錯誤,請稍後再試。');
    }
    

    呼叫動作(dispatch)的語法也只支援兩個參數

    store.dispatch(type, payload)
    
    • type → action 名稱
    • payload → action 唯一能接收的資料

什麼是 Pinia ?

Vuex 有同樣功能,但是又可以完美支援TypeScript,而語法簡單只需一個檔案寫完所有邏輯。

Pinia 檔案彼此關係

  • state:資料來源
  • getter:用 state 生成「計算後」的統計
  • action:放商業邏輯/不分同步或非同步流程(打 API:get/post/patch/delete)
  • 注意:Pinia 取消 mutation,可以直接從 action 修改 state,而不像 Vuex 需透過 mutation
  • 注意:不需要建立 index.js 組起一個 module 使用,一個檔案就是一個 Store,檔案架構更加靈活!

有了管家,但如果有人偷塞奇怪的東西(壞資料)進來怎麼辦?最後一篇,我們請出 TypeScript 衛兵!


圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言