# [Vuex] 基礎介紹
###### tags: `Vue.js`
## vue元件階層處理方式
* 父子階層可透過emit及props做傳遞

* 如非父子層的關係,同階層就得經由eventbus傳遞,不過僅適合在較輕量的專案,因過多易混亂難以管理
* 也能選擇全域變數,但資料無法資料綁定

於是vuex就是為了解決元件層級傳遞的複雜性而被開發出,不論在層級位置都能互相傳遞,也能有雙向綁定的特性

## 總結使用時機
回想頁籤的元件製作,當需要父層的變數值(props取得),也需要呼叫父層的函式(emit呼叫),利用上述兩種方式就可以進行父層子層的溝通。
而在Vuex裡操作能輕鬆的減輕複雜度,把Vuex想像一個雲端空間,裡頭放著很多Methods以及data變數資料,當有任何元件需要時,無論是取變數值、函式,都可以與vuex進行溝通取值(computed裡用mapGetter),或呼叫函式(用dispatch)取得資料,可以說是把所有的運算都放在Vuex進行集中式管理。
## vuex環境架構


actions是指狀態的改變就像是methods的函式,當state的變數需要做更動時,actions是無法直接變更的,需經由代理商mutation當作兩者的媒介。
案例:我們可以看到state跟actions裡的資料完全沒有一點瓜格,都是透過mutations來連結彼此,逐一解釋三者關聯,
* 在mutations裡先命名LOADING為此橋樑的名稱,參數裡載入兩個位置(state預設, actions參數),以此將兩者串連。
* actions也要先命名函式名稱updateLoading,並增加兩個參數,前者是函式內使用的變數,第二則成為payload是傳入mutation裡的參數,內容我們先宣告變數名稱要串連mutations的橋樑名稱,以及順帶將payload參數也傳入即可完成
* 執行流程:html裡寫入`vm.$store.dispatch('updateLoading', true)`,內容主要是呼叫action函式名,並且載入參數true,這時action函式就會進行動作,傳入mutations執行並改變state裡的值,也就是status參數。
# 補充:
1. * 下方案例actions是負責處理函式的部份,函式會帶兩個數值context以及status,context只是單純預設,就如同mutations裡的state一樣,單純是actions及mutation裡的小工人,而status才是帶入的參數。
1. * muations前面有說就是將actions執行的函式結果,經由muations匯入state的變數資料裡
1. * 在執行前面的步驟時,mutations要先命名一個名稱(建議大寫),讓actions知道要匯入哪一個mutations的項目裡。
```
export default new Vuex.Store({
state: {
isLoading: false,
},
//操作行為
actions:{
updateLoading(context, status) {
context.commit('LOADING', status);
},
},
//操作狀態
mutations:{
LOADING(state, status) { //第二個參數是外部傳入
state.isLoading = status;
},
}
});
```
主頁面使用dispatch將需求傳至action裡,並帶指定參數
```
vm.$store.dispatch('updateLoading', true);
```
如果有要回傳變數,則新增computed裡當作state的接口
```
computed: {
cart() {
return this.$store.state.cart;
},
```
### 基本新增項目
1. index.js上新增action + mutations + state
2. vue頁面新增method(dispatch)+ computed
> 補充computed主要是與state變數當作接口
### getters用法
目的:新增getter是為了簡潔vue頁面裡的程式碼,將需要匯集的攏長的程式碼寫在index.js裡
1. 在index.js上新增getters
```
getters: {
categories: state => state.categories,
},
```
2. vue頁面的script下新增import vuex物件,再到computed位置刪除既有的語法刪除,更改成mapGetters
script下新增
```
import { mapGetters} from 'vuex';
```
computed刪除既有的,再寫入mapgetters載入需回傳的變數(可新增多組)。
```
...mapGetters(['categories', 'products']),
```
### mapAction語法
呼叫action函式,可以使用mapAction取代dispatch,也是為了簡潔頁面,增加統一管理性,但如果是要帶參數就不可以使用此語法。
使用mapAction語法,需在script下新增
```
import { mapGetters, mapActions } from 'vuex';
```
並在method裡的呼叫語法裡刪除既有的dispatch語法直接改成mapAction支援的格式
`...mapActions(['getProducts']),`
範例如下:

## 多模組使用概念
執行步驟
新增另一組B模組分類完後,在主模組A要import載入B模組,並在模組A下方新增modules模組載入B模組的名稱即可順利啟用。也就是說模組也是有分父子層,父層仍是匯集地,子層仍要匯入父層才可以使用。
將index.js指令做模組分類,例如:取得商品、前後台
方法
1. 在母模組js裡新增
```
import productsModel from './products';
```
2. 母模組底部新增modules以連結子模組
```
modules:{
productsModel,
}
```
3. 新增子模組即可,同樣依照需求導入axios工具
## 將子模組的函數歸納成區域變數
觀念
預設state是區域變數 / mutation,gutter,actions是全域變數,如有需要宣告或更改就需要調整,因為當全域的狀況下,呼叫action如有相同名稱就會產生錯亂,因此我們可以改成區域變數解決
* 狀況一
因此有一個頁面(是使用子模組)要取用母模組的state變數時,需要寫入modules模組的名稱,例如:this.$store.state.productsModules模組名稱.producs變數名稱
* 狀況二
要將mutation,gutter,actions更改為區域變數,需在母模組新增一行 namespaced : true
* 狀況三
是狀況二的延伸,當有很多組模組時actions函式命名很容易重複,因此使用區域變數是個解決辦法,如此一來在不同模組內相同的函式名稱是可以被接受的,但在啟用函式時,就必須在前面新增B模組名稱當做宣告,例如:...mapGetters('productsModules',['products', 'categories'])
* 觀念結論:
模組主要目的是匯集元件的,但很容易過多的函式指令導致非常混亂,因此模組自身也需要分類,分類後的子模組也需要載入母模組裡的modules裡,也由於是不同位置,因此取用時仍要注意區域、全域變數,在啟用或改變狀態時,都需要依照上方狀況調整,會是比較難操作的部分。
新增namespaced開啟後為“區域變數”

新增root將此段語法變更環境為全域
