3 minutes
Vuex入門 Part2
前言
系列文(?)的第二篇,本篇會以參考三的語法表為主軸,文中範例的環境是以 Vue CLI 以上來說明,可參考Vuex_Todo範例幫助理解。
參考
語法(三步驟說明)
- 使用第一步,把 Vuex 加進 Vue 的實例裡
// main.js, CLI
import Vue from 'vue'
import Vuex from 'vuex'
import store from './store' // Vuex 實例
Vue.use(Vuex) // 等同於 Vue.prototype.$store = Vuex; 讓所有元件都可藉由 this.$store 使用 vuex
new Vue({
el: '#app',
store
})
// with script src, 偶爾在 codepen 上寫寫 Demo 用
// 照順序引入 Vue, Vuex 的 CDN
// 建立 Vuex 實例
var store = new Vuex.Store({
state: {
dataList: []
},
...
})
new Vue({
el: '#app',
store,
data: ...,
computed: {
dataList() {
return this.$store.state.dataList;
},
...
},
...
})
- 使用第二步,建立 Vuex 實例
// store.js
import Vuex from 'vuex'
new Vuex.Store({
strict: true, // 嚴格限制只能通過 mutation 更改 state, 可在開發時確保資料流, 正式環境應關閉
namespaced: false, // 命名空間的啟用/停用, module 專用, 幫資料和方法取名總有靈感枯竭的狀況, 使用說明參考上方namespaced說明連結
modules: {}, // 載入子層資料, 如 store.js 載入 user.js, user.js 再載入 post.js, 形成 store/user/post的關係
state: {}, // 等同於 Vue 的 data, 放預設資料的地方
getters: {}, // 等同於 Vue 的 computed, 回傳加工過的資料
mutations: {}, // 類似於 Vue 的 methods, 負責更改 state, 只能使用同步操作
actions: {}, // 類似於 Vue 的 methods, 異步(ex:發 API 取資料)會集中在這裡處理,發 commit 到 mutation 更改 state
plugins: [], // 類似於 Vue 的 watch, 初始化時會在 created 後執行一遍, 使用說明參考上方plugins說明連結
devtools: false, // 使 Vue.js devtools 忽略這個 store
})
// vuex 屬性下放的方法有設定一些參數
Vuex.Store({
state: {
num: 0,
},
mutations: {
counter(state, payload) {
state.num += payload; // padload 為可選參數, 不限制型別, 傳遞更改 state 前需要的運算值
}
},
actions: {
/*
context 物件解構後包含以下屬性
{
state, // 等同於 store.state, 若在 module 中則為局部 state, 也就是只取得到自己及載入的 module 的資料
rootState, // 等同於 store.state, module 專用, 用來取得父層資料
commit, // 等同於 store.commit, 要求 mutation 更改資料
dispatch, // 等同於 store.dispatch, 觸發其他 action
getters, // 等同於 store.getters, 取得 getter 處理過的資料
rootGetters // 等同於 store.getters, module 專用, 用來取得父層 getters
}
*/
calculator(context, payload) {
// do something ...
commit('counter', payload); // 要求 counter mutation 更改 state
}
},
getters: {
/*
getter 在父層中可傳入兩個參數
第一是 state, 取得當前 store 的 state
第二是 getters, 取得其他 getter 輔助計算
getter 在 module 中可傳入四個參數
第一是 state, 取得當前 store 的 state
第二是 getters, 取得其他 getter 輔助計算
第三是 rootState, 取得父層 state
第四是 rootGetters, 取得父層 getters 輔助計算
*/
getNum: (state, getters) => {
// do something ...
return state.num;
}
}
})
- 使用第三步,元件使用 Vuex 方法有二:
// 第一,已使用過 Vue.use(Vuex),可通過 this.$store 使用
export default {
// ...
computed: {
getTodos() {
return this.$store.getters.doneTodosCount;
}
// 因應 Namespace 的使用狀況
getCounter() {
return this.$store.moduleName.getters.counterCount;
}
}
}
// 第二,使用 Vuex 提供的輔助方法,{ mapState, mapGetters, mapActions, mapMutations }
// mapActions, 把 this.incrementBy(amount) 映射為 this.$store.dispatch('incrementBy', amount)`
// mapMutations, 把 this.incrementBy(amount) 映射為 this.$store.commit('incrementBy', amount)`
// 因應 Namespace 的使用狀況, dispatch 與 commit 可帶第三個參數為 { root: true }, 用途等同於 root 開頭的那幾個, 於 module 中使用
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
...mapGetters([ // 把 this.firstGetter 映射為 this.$store.getters.firstGetter
'firstGetter', // 等同於 firstGetter: 'firstGetter'
anotherGetter: 'secondGetter', // 或是取個比較好懂的名稱
// ...
]),
// 因應 Namespace 的使用狀況
...mapGetters([
'paraentName/fourthGetter'
]),
...mapGetters('LevelOne/LevelTwo/LevelThree', [
'thirdGetter'
]),
}
}
其他
Vuex 還有很多細節是兩篇文章講不完的,麻煩自己到官方文件看,這邊還要介紹一個好用的功能,註冊/卸載 module,用法類似 Vue 的 mixin,重點在於動態、重用,不過記得要在 beforeDestroy 時把 module 和監聽事件一起卸載掉。
// 註冊
store.registerModule('myModule', {
// ...
})
// with Namespace nested/myModule
store.registerModule(['nested', 'myModule'], {
// ...
})
// 卸載
store.unregisterModule('myModule')
結語
雖然 Vuex 還在更新,但我不會再更新這篇文章,使用上的觀念不會變。 如果你看到這邊覺得暫時用不到 Vuex,可看參考四的 EventBus,可以不用管這堆麻煩的使用方式,開新檔建立新的 Vue 實例,在需要共用資料的元件引入並共用這個實例的 data、methods…等等,也能暫時解決問題,但資料越多越難管理。