iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Modern Web

Vue.js 什麼意思系列 第 21

Day 21:總匯複習-Vuex、Route

前幾篇介紹了 Vuex 管理資料狀態,以及在生命週期或導航守衛發送 API 的時機點,再次回到專案範例,目前已處理好顯示導覽列中的全部書單內容,我們接續完成其他導覽項目所需要的畫面資料。

Vuex 狀態整理

  • action 發送 API 後將資料以 commit 呼叫 mutation

    actions: {
        async fetchBookList(context) {
            const books = await GET();
            context.commit("bookList", books);
        },
    },
    
  • mutation 將資料直送並賦值給 state

    state: {
        bookList: {},
    },
    mutations: {
        bookList(state, books) {
            state.bookList = books;
        },
    },
    
  • getters 取得 state 資料

    • 方式一:從 state 拿取同一份資料,再各別進行資料處理

      getters: {
        allBooks: (state) => state.bookList.list,
        discount30Books: (state) =>
          state.bookList.list.filter(
            (book) =>
              0.7 <= book.sellPrice / book.originPrice &&
              book.sellPrice / book.originPrice < 0.8
          ),
        discount50Books: (state) =>
          state.bookList.list.filter(
            (book) =>
              0.5 <= book.sellPrice / book.originPrice &&
              book.sellPrice / book.originPrice < 0.6
          ),
        ithelpBook: (state) =>
          state.bookList.list.filter((book) => book.name.includes("鐵人賽")),
      },
      
    • 方式二:透過拿取其他 getters 再加工處理,當遇到重複的篩選條件也可合併為一個共用函式加以簡化

      getters: {
        allBooks: (state) => state.bookList.list,
        discountBooks: (state, getters) => (min, max) =>
          getters.allBooks.filter(
            (book) =>
              min <= book.sellPrice / book.originPrice &&
              book.sellPrice / book.originPrice < max
        ),
        discount30Books: (state, getters) => getters.discountBooks(0.7, 0.8),
        discount50Books: (state, getters) => getters.discountBooks(0.5, 0.6),
        ithelpBook: (state, getters) =>
          getters["allBooks"].filter((book) => book.name.includes("鐵人賽")),
      }
      
  • 最後,在元件內的 computed 取用 getters 的資料

    computed: {
        books() {
            return this.$store.getters["allBooks"];
        },
    },
    

資料處理:getters VS computed

以上算是發送 API 和資料處理的基本流程方向,但因應每個人的開發習慣多少還是會有差異。有些人的作法可能會根據資料的共用範圍決定處理資料的時間點:

  • 在 getter 先處理好資料內容 → 提供給多個元件共用相同資料
  • 在 getter 單純回傳原始資料 → 在單一元件內再針對篩選條件處理資料

目前的做法會是統一都在 getters 處理資料,因此在元件內只需單純取用 getter 即可,如此一來我將所有的複雜邏輯集中在 getters 做好管理,當資料有任何錯誤情形發生時,就不用再回想資料有沒有共用情形、當初是放在哪一邊處理邏輯等瑣碎問題,而來回在 getters 和 computed 之間檢查程式碼。

發送 API 的時機點

回到 Vuex 的開頭以 dispatch 呼叫 action,選擇在適合的導航守衛位置發送 API。

  • 全域 beforeEach 發送 API:看似快速又方便,但是進入其他不需要書單資料的頁面時也會跟著發送 API。

    router.beforeEach(async (to, from, next) => {
      await store.dispatch("fetchBookList");
      next();
    });
    
  • 路由 beforeEnter 發送 API:將導覽項目路由規劃成巢狀結構,直接在父層路由發送 API。

    {
        path: "/book",
        redirect: { name: "All" },
        component: MainPage,
        beforeEnter: async (to, from, next) => {
          await store.dispatch("fetchBookList");
          next();
        },
        children: [
          {
            path: "all",
            name: "All",
            component: All,
          },
          ...  // 略
        ],
    },
    

在頁面中新增顯示書單筆數。
all

切換導覽項目時,能更明顯確認不同頁面所串接的資料差異。
ithelp

由於所有導覽項目頁面內的排版一致,因此可將排版另外包成一個元件,之後也會陸續介紹元件之間傳遞資料的方式。


上一篇
Day 20:全域、路由、元件內-Navigation Guards
下一篇
Day 22:兒子乖聽爸的話-Props 傳入資料
系列文
Vue.js 什麼意思30

1 則留言

0
justlikett
iT邦新手 5 級 ‧ 2021-11-24 16:39:57

請問一下 有完整的程式碼 可以參考嗎?
因為我跟著打,但是無法跟你一樣能呈現出來!!

我要留言

立即登入留言