使用 Vuex 管理資料狀態
瞭解 Vue 的指令、元件、路由配置等概念後,我們用 Vue CLI 製作的網站差不多告一段落了!然而 Vue 生態圈還有一個必備技能是 Vuex,我們現在就來把 Vuex 也加入專案,讓我們的資料狀態可以跨元件同步。
Why Vuex
我們之前要做父子元件間的資料傳遞時,會使用 Props 與 Emit,同層級元件間則使用 Event Bus,透過以上方式我們就能在各個元件間互相溝通了。
但是,在多層的情況下,相當不推薦用 Props 與 Emit 一層傳一層,而 Event Bus 如果跨很多層或資料量大,也不建議使用,這時我們就需要一個更完善的跨元件溝通方式哩,而 Vuex 就是在提供一個狀態管理中心,將原先「通知」的概念,直接昇華到「共享狀態」的層次。
What is Vuex
其實 Vuex 的概念簡單來說就是把 Vue 元件裡面的資料或方法移到 Vuex 去做管理。
在這個統一管理的概念下,任何一個元件都能呼叫 Vuex 裡頭的方法,並且維持雙向綁定的特性,而這些存進來統一管理的資料與方法,在 Vuex 中我們叫它Store。
Getting Started - 運作流程與使用方式
首先 Vuex 有 State、Getters、Actions、Mutations 這四個主要核心元素,先來簡單敘述一下這四個元素是用來幹嘛的。
- State:各元件間共享的資料狀態,在使用上類似於元件裡面的
data
- Getters:類似
computed
的感覺~ - Actions:用法如同
methods
,但是只做非同步行為、取得資料等等,不能改變state
裡面的資料 - Mutations:這裡可以進行改變資料內容的方法,只做同步的行為
在 Vue 的 Single File Components 裡面,我們會用以下流程操作 Vuex 來存取共享的資料狀態:
- 透過Dispatch方法觸發 Actions 裡面的 Function 完成非同步行為,像是去取得遠端資料(透過 AJAX、Axios 呼叫遠端 API)
- 使用Commit呼叫 Mutations 來改變 State(改變資料狀態)
- 最後把資料渲染回到畫面上呈現
第一步的 Actions 是在取得資料,還沒有改變 State 裡面的資料,改變資料狀態要到 Mutations 這個階段才會更改。
以上這三個步驟大概就是 Vuex 的運作流程了,比較進階一些的使用方式我們先留到下一篇再介紹,接下來我們先透過範例操作一次吧!
STEP 1:監聽資料狀態
這邊就以我自己的專案MapleStory Shop資料轉移到 Vuex 的過程作為範例。
專案中我使用 vue-loading-overlay 套件來製作過場動畫,因為這個效果各頁面都會呼叫去做轉圈圈的動畫,所以就需要跨元件溝通哩。
基本的建置環境與安裝方式可參考Vuex 官方文件,這邊主要會說明使用方式。
首先,因為我們要管理 isLoading
這個資料狀態,所以我先新增 isLoading
到 state
之中。
1// store/index.js 2 3import Vue from 'vue'; 4import Vuex from 'vuex'; 5 6Vue.use(Vuex); 7 8export default new Vuex.Store({ 9 state: { 10 isLoading: false, 11 }, 12}); 13
接著在元件中透過 computed
監聽資料的變化。
1// App.vue 2 3export default { 4 name: 'App', 5 computed: { 6 isLoading() { 7 return this.$store.state.isLoading; 8 }, 9 }, 10}; 11
STEP 2:實作 Actions
新增資料後,我們可以在 store
中註冊 actions
方法來觸發事件。
首先,Actions 可以帶兩個參數,第一個是必要的參數 context
,而第二個參數是可選的參數,如果你懶得想名稱,可以都用官方定義的 payload
(載荷)就好,不過建議替換成符合當下用途、語意化的名稱。
這個 payload
用來把方法中會使用到的參數帶進來,如果超過一個可以用物件的方式放入參數,像是 context.commit('LOADING', {param1, param2})
。
1actions: { 2 updateLoading(context, status) { 3 context.commit('LOADING', status); 4 }, 5}, 6
STEP 3:實作 Mutations
前面有提到 actions
的方法只是在取得資料,並不能操作資料狀態,要操作資料狀態必須是在 mutations
裡面。
所以我們就來註冊一個 mutations
,它也有兩個參數,與 actions
一樣,第一個參數固定是 state
,就是我們上面提到的資料狀態,而另一個也是 payload
,是從外部傳進來的參數。
這個 payload
就是從剛才的 updateLoading
傳過來的 status
,所以這裡直接帶入 status
作為第二個參數即可。
1mutations: { 2 LOADING(state, status) { 3 state.isLoading = status; 4 }, 5}, 6
現在我們就可以藉由 acions
裡面的 context.commit('LOADING', status)
來觸發 LOADING
這個 mutations
來修改資料狀態哩。
在元件裡面就是透過 Dispatch
去操作 actions
裡面的方法,達到共享資料狀態的效果!
官方建議 Mutations 以常數(全部大寫)的方式來命名,這樣會比較好辨識。
簡單說明 Actions 與 Mutations 的差異
Actions 與 Mutations 的主要差別就是 Actions 做非同步行為,而 Mutations 做同步行為。
舉例來說,像是 AJAX 或是 setTimeout
這種非同步的行為,因為會讓資料狀態與 payload
不一致,所以這些非同步行為應該在 actions
裡面完成,不要在 mutations
在更換資料時使用。
如果怕不小心寫錯,建議可以加上 strict: true
來啟用嚴謹模式。
開啟後,如果你不小心透過 Mutations 以外的方法來改 state
的數值,像是在 Actions 裡面直接做更改的話,Vuex 會自動跳出警告,提醒你這並非正確的撰寫方式囉,建議開起來以免寫錯哩!
以上資源是我自己整理過後的筆記,若有錯誤歡迎隨時和我聯繫