[Vue] Vuex 是什麼? 怎麼用? — Actions (2/5)

itsems
itsems_frontend
Published in
8 min readApr 19, 2020
全系列共五篇:
一、[Vue] Vuex 是什麼? 怎麼用? — State、Mutations (1/5)
二、[Vue] Vuex 是什麼? 怎麼用? — Actions (2/5)
三、[Vue] Vuex 是什麼? 怎麼用? — Getters (3/5)
四、[Vue] Vuex 是什麼? 怎麼用? — Modules (4/5)
五、[Vue] Vuex 是什麼? 怎麼用? — 統整、專案結構(5/5)
Outline:
1. Actions & Mutations
2. Actions & Mutations with Payload
3. mapActions

Actions & Mutations

在上篇的時候有說過:

在 Vuex 裡面,儲存狀態的為 State,組件需要更動狀態時,需要透過 Actions 發出一個 Commit 去呼叫 Mutations,再由 Mutations 去更改 State

上篇說明了怎麼使用 Mutations 去改變 state,現在來看 Actions 要怎麼發出一個 commit 去呼叫 Mutations。

Mutations 只能做同步的操作,如果有非同步的需求,則要使用到 Actions,Actions 發出 commit 呼叫 Mutations,讓 Mutations 去改變 State 的狀態,Actions 不能直接修改 State,只有 Mutations 可以更改 State。

為了示範在 Actions 非同步的操作,這次的範例來試著抓 randomuser 這個線上可以隨機抓出 user 資訊的 API,另外搭配 axios 來使用

跟著 npm 的步驟安裝 vue-axios 就可以了

在這個範例中,我想要 Load random user 的 API,Load 好之後,改變我的 state 狀態為 true

設定好情境之後,就來 store.js 定義需要的內容:

也可以用 ES6 解構的方法將 context 裡面的 commit, dispatch 解構出來使用:

ps. actions 裡面可以 commit 多個 mutations,也可以 dispatch 多個 actions

所以在 GetUser 這個函式中,做了三件事情,

  1. 吃 randomuser API
  2. 吃到之後,執行 MyMutations 這個 mutations (會改變 state 的 loaded)
  3. 吃到之後,執行 AnotherActions 這個 actions (會 console 出 "Another Actions run!")

在 mutations 裡面,SetFalse 則會把 state 的 Loaded 改為 false,因為我想要在頁面加一個 reload 的按鈕,點擊後要把 Loaded 狀態改為 false,再重抓一次 API。

接下來,就來 app.vue 寫 template:

<div id="app">
// state 的 Loaded
<p>random user api Loaded: {{userLoaded}}</p>
// Reload API
<button @click="Reload">Reload</button>
</div>

在 script 中,會做三件事情

  1. 頁面讀取完成時,吃 randomuser API
  2. 將 state 中的 Loaded 用 computed 抓出來給 userLoaded 做使用
  3. Reload 按鈕按下去的時候,把 state 的 Loaded 改回 false,然後再執行一次 GetUser 這個 actions

三件事情寫進來就會是這樣:

都寫好之後,就用 npm serve 來看看成果:

另外在 chrome 的 Vue.js devtools 中,其實也有一個 Vuex 標籤頁可以讓我們看到 mutations 執行的歷史紀錄

我的主題是 dark theme,預設是白色主題,不影響使用

打開 devtool 選到 Vue 就可以看到 Vuex 這個標籤頁,或者按 Ctrl +2 也可以快速切換。切換到 Vuex 分頁後,這邊可以看到執行過的 vuex 的 mutations,以我們的範例,一進入頁面所執行的 actions GetUser 會先觸發一次 MyMutations ,點擊 Reload 按鈕後,會再觸發 SetFalse ,接著再一次 GetUser 裡面的 MyMutations ,動作如下:

點擊一次 Reload 就會看到依序執行了 MyMutationsSetFalse,另外右邊也可以看到 state 的變動,再透過 Time Travel 就可以回朔到當時的 state 狀態

Actions & Mutations with Payload

簡易的 actions 差不多就是這樣,接下來再來加上 payload 的 mutations

除了 load random user API 之外,我想要每一次點 butotn 都加 2 次 Click 次數

跟上一篇的範例有點像,只是這邊我要把點擊次數由 actions 帶給 mutations,先從 store.js 開始,在 state 加上一個 clickedTimes 預設為 0:

state: {
Loaded: false,
clickedTimes: 0
},

接著加上一個 actions 名為 ClickedActions ,並在參數中使用解構 commit,帶上 payload:

ClickedActions({ commit }, payload) {
commit('addTimes', payload)
}

mutations addTimes

addTimes(state, payload) {
state.clickedTimes = state.clickedTimes + payload;
}

這樣 store.js 就設定完了,接下來進入 app.vue。

在 template 加上我們想要顯示次數的內容:

<p>Button Clicked Times: {{clickedTimes}}</p>

computed 就不贅述了,跟上回合帶出 state 的方式一樣,再來在 Reload 的 methods 這邊,帶入含 payload 的 dispatch:

this.$store.dispatch("ClickedActions", 2);

這樣就完成了,在這邊的 dispatch 帶上 payload 的方式也跟 mutations 很像,除了這樣寫,也可以使用物件:

this.$store.dispatch("ClickedActions", {count: 2});

在這邊改成物件的話,mutations 的計算方式就變成加上 payload.count ,也是一樣。

或著要直接帶入整個物件:

this.$store.dispatch({ type: "ClickedActions", count: 2 });

和 mutations 一樣, type 是必須的,其他則隨意

mapActions

再來就可以用上 actions 也有的 mapActions 了,一樣 import mapActions 之後,我們試著把剛剛所有的 dispatch 用 mapActions 把 actions 取出來使用:

總共有三個呼叫 actions 的 dispatch,引用 mapActions 之後,就等於這些 actions 都撒在 component 的 methods 可以使用(ES6),所以取出來之後,都可以直接用 this.xx 呼叫:

actions 的說明差不多就到這邊了,總結一下重點

commit 拿來呼叫 mutations,dispatch 拿來呼叫 actions
actions 不能直接變動 state,只有 mutations 可以更動 state

--

--

itsems
itsems_frontend

Stay Close to Anything that Makes You Glad You are Alive.