整理 Vuex 筆記
流程與說明
用下列二張圖,簡易表示 Vuex 的概念。
單向數據流
與 Vue 相似之處
State
存放所有要共用的變數
1 | // store.js |
1 | // .vue |
Getter
如同 computed,用來取得 state
裡的變數值,或者經過計算、篩選的 state 值
1 | // store.js |
1 | // .vue |
範例
分別敘述下列三種用法
- 用法 1:計算 尚未 Done 的項目
- 用法 2:計算 已 Done 的項目
- 使用
getters
參數,取得原先已有的itemsNotDone
函式
- 使用
- 用法 3:透過外層「傳遞傳數」,再加以運算出結果
1 | // store.js |
達到傳遞傳數的方式,需配合上述的「用法 3」的設定
1 | import { mapState, mapGetters } from 'vuex'; |
延伸上例,
有可能會遇到不同Modules,卻命名到一樣名稱的話,
這時我們可以利用「更名」方式,避免實際運用時,產生衝突。
1 | import { mapState, mapGetters } from 'vuex'; |
Mutations
用於更改 state 裡的變數。
注意: 請記住所有要更改 state
的變數值,都只能透過 mutations 進行更改。
1 | // store.js |
1 | // .vue |
觸發 Mutations
承上例,
若要觸發 Vuex 的 mutations,因為我們有解構賦值 mapMutations 裡的 methods,
所以就直接使用即可,不建議使用this.$store.commit
的方式,
如下所示
1 | // .vue |
Actions
如同 methods,
在執行過程中,可透過 AJAX 取的資料後,再計算分析後,將結果回塞給 state
裡的變數值,
But…剛剛上面說過,所有要更改 state
的變數值,都只能透過 mutations 進行更改。
1 | // store.js |
1 | // .vue |
Mutations vs Actions
說明二者的差異點,
另外需注意的是「Mutations 和 Actions」都是解構賦值至 vue 的 methods 位置,
所以要注意二者的 Function Name 是否有衝突。
Mutations
Mutations 一定要是「同步式」更改 state 的變數值,不可以是「非同步」更改變數值。
錯誤範例
1 | // store.js |
正確範例
1 | // store.js |
Actions
Actions 可以是非同步更改 state 的值,
但在 strict(嚴格) 模式下,Actions 不應該直接更改 state 的值,
而且是要 Actions 觸發 Mutations 去改 state 的值。
非嚴格模式(不推)
1 | // store.js |
嚴格模式(建議)
1 | // store.js |
Action 傳送多個值
因為 Action 的接收參數只有二個,而第一個參數固定是 context
,
所以只剩第二個參數可以傳送「資料」,若只有一個值的話,沒什麼問題,
但如果同時間,要傳送多筆資料,又卡在只剩一個參數可塞值的話,
該如何解決呢?
參數
- 第一個參數:context
- 第二個參數(可選):payload
context
對象包含以下屬性:
1 | { |
官方 API:Action
範例(單個值)
1 | methods: { |
範例(多個值)
籍由傳送 物件 並透過 解構賦值 的配合,達到傳遞多筆資料。
1 | // store.js |
1 | // .vue |
Action 非同步處理多事件
有時我們可能要完成一個事的話,需等待前一個 AJAX 回傳結果,才能繼續執行下一步驟,
這樣的話,我可以利用 promise 完成此事。
範例
下列為要完成 actionB
的動作時,事前需先完成 actionA
的事情,
所以 actionA
多包一層 promise
來回應,
而 actionB
則用 .then
來等待上一事件完成,
才會繼續執行後續動作 commit('someOtherMutation')
1 | actions: { |
Module 模組化
簡單來說,就是原本全部都寫在 store.js 裡的程式,
全部拆分一支支的模組 js,各別存放有相互關係的功能,
最終再透過 Vuex 的 modules 引入各個模組。
事前提醒
當我們將 store.js 裡,部份程式拆分為模組 js 時,
此時模組 js 的程式作用域如下:
- state 屬於模組「區域」變數
- actions、mutations、getters 仍是屬於「全域」變數
所以當不同模組裡,有命名到「相同名稱」的話,就會出現錯誤訊息,
只要我們將名稱不要重覆即可,並不是一件很嚴重的事,
我們也可以從命名的方式,用來分辦是屬於哪個模組內的 methods。
官方:命名空间
高封裝度和復用性
如果希望你的模塊具有更高的封裝度和復用性,
你可以通過添加 namespaced: true
的方式使其成為帶命名空間的模塊,
這時「actions、mutations、getters」就變成「區域」變數。
範例
將原本在 store.js 拆解出 「產品模組、購物車模組」,
剩下共用的部份,依舊放在 store.js 裡即可,
如:畫面 loading 效果
1 | // 產品模組 |
1 | // 購物車模組 |
1 | // store.js |
1 | // .vue |
細節可參考下列連結:
不同模組函式名稱重覆
當我們開始拆分模組時,很有可能在不同模組下,命名到同樣名稱的函式,
這樣當我們在 Vue 引用時,很可以就會產生衝突。
情況
假設 A 模組 和 B 模組 裡,同時有相同 Actions 的名稱叫「setFilter」的話,
這時又要同時引入的話,該怎麼處理呢?
1 | export default () { |
官方:在组件中分发 Action
Vuex: Actions with same name in different modules