# [Vuex] 基礎介紹 ###### tags: `Vue.js` ## vue元件階層處理方式 * 父子階層可透過emit及props做傳遞 ![](https://i.imgur.com/eWcb5Kr.png) * 如非父子層的關係,同階層就得經由eventbus傳遞,不過僅適合在較輕量的專案,因過多易混亂難以管理 * 也能選擇全域變數,但資料無法資料綁定 ![](https://i.imgur.com/ZyoHVbi.png) 於是vuex就是為了解決元件層級傳遞的複雜性而被開發出,不論在層級位置都能互相傳遞,也能有雙向綁定的特性 ![](https://i.imgur.com/Xn2e3aq.png) ## 總結使用時機 回想頁籤的元件製作,當需要父層的變數值(props取得),也需要呼叫父層的函式(emit呼叫),利用上述兩種方式就可以進行父層子層的溝通。 而在Vuex裡操作能輕鬆的減輕複雜度,把Vuex想像一個雲端空間,裡頭放著很多Methods以及data變數資料,當有任何元件需要時,無論是取變數值、函式,都可以與vuex進行溝通取值(computed裡用mapGetter),或呼叫函式(用dispatch)取得資料,可以說是把所有的運算都放在Vuex進行集中式管理。 ## vuex環境架構 ![](https://i.imgur.com/ubvsqZ6.png) ![](https://i.imgur.com/VueGkLE.png) 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']),` 範例如下: ![](https://i.imgur.com/0tYC1JI.png) ## 多模組使用概念 執行步驟 新增另一組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開啟後為“區域變數” ![](https://i.imgur.com/NuCvqMY.png) 新增root將此段語法變更環境為全域 ![](https://i.imgur.com/SshZHPf.png)