0%

[Vue] Vuex 資料狀態管理學習筆記之模組化資料運用

這系列到目前為止,其實已經把 Vuex 基本的使用方式介紹得差不多了。
而本篇則是會介紹一些比之前進階一點的寫法,也就是將 Vuex 中管理的資料模組化,並以與之前不同的形式在元件中讀取資料。

Vuex 中的 getters, mapGetters, mapActions

這一段要介紹的是:在元件中提取 Vuex 函式的新方法。

  1. 在 store 中加上 getters 物件,把在元件中要用 computed 呈現在畫面上的資料移進來。移進來的形式是 function 形式,且帶入跟 mutations 一樣的參數(state)。
1
2
3
4
5
6
7
8
getters: {
categories(state) {
return state.categories;
},
products(state) {
return state.products;
}
}
  1. 到要呈現畫面的元件中(Home.app),引入 Vuex 中的 mapGetters,注意,要用物件包住要引入項目。
1
import { mapGetters } from 'vuex';
  1. 移除原本 computed 中定義的資料函式,改用展開符號mapGetters 的內容取出來,並指定要取出裡面的哪些 gettets。
1
2
3
4
5
computed: {
...

...mapGetters(['categories', 'products']),
}
  1. 除了 mutations 可以改成 gettersactions 也能用這種方法,從 store 取出來用在元件上。首先在引入的地方,多增加 mapActions 的引入。
1
import { mapGetters, mapActions } from 'vuex';
  1. mapActions 可以用來替換元件中不需要帶入參數methods 函式,例如以下這樣:
1
2
3
4
5
6
7
// 原本是這樣
getProducts() {
this.$store.dispatch('getProducts');
}

// 用 mapActions 帶入
...mapActions(['getProducts']),

補充說明:mapActions 的使用時機

mapActions 的使用時機,最簡單的辨別方式就是「需不需要帶入參數」,若需要就不能使用 mapActions

模組化資料運用

場景從元件切回到 store。

接下來我們要把 store 中的程式碼再做拆分(模組化),例如,將行為及資料分為兩大類:「取得產品」類及「取得購物車、新增刪除品項」類。

以下以「取得產品」類為例,示範如何將資料模組化。

  1. 在 store 資料夾新增 products.js

  2. 在裡面寫好 export default {} 後就可以複製 store 中的程式碼,移到這個物件裡。但因為這個檔案只放與產品相關的行為,所以跟購物車、讀取效果有關的程式碼就先移除。

  3. 把 axios import 進來

  4. 回到 store/index.js,把已經拆出去的程式碼刪掉,然後引入 products.js,並且幫 products.js 取一個模組名稱叫做 productsModules

1
import productsModules from './products';
  1. 一樣是在 index.js 中,在 getter 物件下方新增 modules 物件,在裡面直接貼入 modules 名稱。
1
2
3
modules: {
productsModules,
}

模組重要概念

在 products.js 中,state 是模組內的區域變數,除此以外 actionsmutationsgetters 等都是全域變數

所以如果 store 中有其他模組使用與 products.js 相同名稱的 actionsmutationsgetters,就會出現錯誤。

如果在元件中想要讀取模組的 state 變數,要這樣寫:

1
2
console.log(this.$store.state.productsModules.products);
// state 後面還要多一層 productsModules 才讀得到模組內的資料

如果希望 actionsmutationsgetters 都變成模組內的區域變數,該怎麼做?

只要在 state 上一行加上 namespaced: true,它們就都會變成區域變數了,但此時元件就沒辦法直接讀到這些行為。

解決方法是,當使用 mapGetters() 時,也把模組名稱帶進來:

1
...mapGetters('productsModules', ['categories', 'products']);

不過,當元件內同時要讀取模組資料及全域資料時,就要標示出哪些是全域資料,標示的方法是在 commit() 中帶入 { root: true } 當參數:

1
2
// LOADING 是定義在 index.js 中的全域變數
context.commit('LOADING', true, { root: true });

Vuex 筆記到此差不多告一個段落了~

這些筆記都是我在上六角學院的 Vue.js 課程中寫下的筆記,不過我可能還是有寫得不夠仔細的地方,
所以附上兩個我覺得整理得很不錯的文章給各位一起參考: