模組化資料運用

Veux 最大的好處在於可以將原先獨立於各原件中的行為統一放到 store 中管理,並提供其他原件取用,但當專案變大時,如果所有的行為都放到同一支檔案中管理,這隻檔案將會變得非常龐大,因此 Vuex 提供了模組化的方式來拆分其中的行為

假設專案中有別有產品與購物車兩大類,在這裡我們將產品類拆分出來,首先在 store 中新增一支 product.js ,並將所有與產品有關的行為都放到這之檔案中,同理在 index.js 中移除與產品相關的行為,如有有使用到 AJAX axios 也要在這裡載入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// in product.js
import axios from 'axios';

export default {
state: {
products: [],
categories: [],
},
actions: {
getProducts() {},
},
mutations: {
PRODUCTS(state, payload) {
state.products = payload;
},
CATEGORIES(state, payload) {
state.categories = payload;
}
},
getters: {
products: state => state.products,
categories: state => state.categories,
}
}

載入拆分出去的檔案

拆分出去後,在 index.js 中透過 import 的方式在入拆分出去的 product.js,並新增一個 modules 的物件來取得檔案

1
2
3
4
5
6
7
8
9
10
// in index.js
import productsModules from './products';

export default new Vuex.Store({
state: {},
actions: {},
mutations: {},
getters: {},
modules: { productsModules },
});

區域與全域

在這裡有一個很重要的觀念要注意,當我們拆分檔案時,模組中每個屬性的預設作用域並不相同

  • state: 屬於模組區域變數
  • actions, mutations, getters: 屬於模組全域變數

所以當不同模組在 state 以外存在相同名稱時,就可能會出現錯誤

取得模組中變數

如果要取得拆分出去的模組中的 state 變數就要在前方指定模組名稱才能取得

1
2
3
4
5
6
7
// in component

methods: {
addtoCart() {
console.log(this.$store.state.productModules.products);
}
}

將 “全域變數” 轉換成 “區域變數”

先前提到,state 以外的屬性預設都是全域變數,所以如果在不同模組出現相同的名稱就會出現錯誤,在這裡可以新增一個屬性來將 “全域變數” 轉換成模組內的”區域變數”

1
2
3
export default {
namespaced: true,
}

指定模組行為

但如果將模組內的行為轉換成區域變數,就會出現無法直接取得的情況,所以在元件取得模組中的行為時,要在前方指定模組名稱

1
2
3
4
5
6
7
8
9
10
11
12
// in component
import { mapGetters, mapActions } from 'vuex';

export default {
data() {return},
computed: {
...mapGetters('productsModules', ['categories', 'products']),
},
methods: {
...mapActions('productsModules', ['getProducts']),
}
}

模組間取得全域變數

將模組中 state 以外的屬性區域化後,如果有取得其他模組中的屬性,就要在後方標註全域 { root: true }

1
2
3
4
5
6
7
// in products.js

actions: {
getProducts(context) {
context.commit('LOADING', true, { root: true });
}
}

元件中透過 dispatch 呼叫模組方法

如果是在元件中呼叫拆分出去的模組中的方法,在指定模組名稱時,直接加在前方即可,並透過斜線 / 隔開

1
2
3
4
5
6
7
// in component

methods: {
removeCart(id) {
this.$store.dispatch('cartModules/removeCart', id);
},
}

取得其他區域化元件中的 actions 行為

如果要取得的是其他區域化元件 actions 中的行為,不僅要在前方指定模組,還要在後方加上 { root: true } 代表從根節點開始查找

1
2
3
4
5
6
// in one.js
actions: {
test(context) {
context.dispatch('two/event', parameter, { root: true )
}
}