能夠認爲是store的計算屬性;與計算屬性同樣,getter的返回值會根據它的依賴緩存起來,且只有當它的依賴值發生變化纔會被從新計算vue
輔助函數僅僅是將 store 中的 getter 映射到局部計算屬性:vuex
import { mapGetters } from 'vuex' export default { // ... computed: { // 使用對象展開運算符將 getter 混入 computed 對象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter', // ... ]) } }
更改vuex的store中的狀態的惟一方法就是提交 mutations
在 mutation 中混合異步調用會致使你的程序很難調試。例如,當你能調用了兩個包含異步回調的 mutation 來改變狀態,你怎麼知道何時回調和哪一個先回調呢?api
mutation必須是同步函數緩存
mutations: { someMutation (state) { api.callAsyncMethod(() => { state.count++ }) } }
如今想象,咱們正在 debug 一個 app 而且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,devtools 都須要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的異步函數中的回調讓這不可能完成:由於當 mutation 觸發的時候,回調函數尚未被調用,devtools 不知道何時回調函數實際上被調用——實質上任何在回調函數中進行的狀態的改變都是不可追蹤的。app
你能夠在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations
輔助函數將組件中的 methods 映射爲 store.commit 調用(須要在根節點注入 store)。異步
import { mapMutations } from 'vuex' export default { // ... methods: { ...mapMutations([ 'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')` // `mapMutations` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.commit('incrementBy', amount)` ]), ...mapMutations({ add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')` }) } }
你在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用 mapActions
輔助函數將組件的 methods 映射爲 store.dispatch 調用(須要先在根節點注入 store):async
import { mapActions } from 'vuex' export default { // ... methods: { ...mapActions([ 'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')` // `mapActions` 也支持載荷: 'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)` ]), ...mapActions({ add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')` }) } }
Action 一般是異步的,那麼如何知道 action 何時結束呢?更重要的是,咱們如何才能組合多個 action,以處理更加複雜的異步流程?函數
首先,你須要明白 store.dispatch 能夠處理被觸發的 action 的處理函數返回的 Promise,而且 store.dispatch 仍舊返回 Promise:post
// 假設 getData() 和 getOtherData() 返回的是 Promise actions: { async actionA ({ commit }) { commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // 等待 actionA 完成 commit('gotOtherData', await getOtherData()) } }
因爲使用單一狀態樹,應用的全部狀態會集中到一個比較大的對象;當應用變得很是複雜時,store 對象就有可能變得至關臃腫。this
爲了解決以上問題,Vuex 容許咱們將 store 分割成模塊(module)。每一個模塊擁有本身的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行一樣方式的分割:
const moduleA = { state: { ... }, mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: { ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } }) store.state.a // -> moduleA 的狀態 store.state.b // -> moduleB 的狀態
若是你但願使用全局 state
和 getter
,rootState
和 rootGetter
會做爲第三和第四參數傳入 getter,也會經過 context 對象的屬性傳入 action。
默認狀況下,模塊內部的 action、mutation 和 getter 是註冊在全局命名空間的——這樣使得多個模塊可以對同一 mutation 或 action 做出響應。
若是但願你的模塊具備更高的封裝度和複用性,你能夠經過添加 namespaced: true 的方式使其成爲命名空間模塊。當模塊被註冊後,它的全部 getter、action 及 mutation 都會自動根據模塊註冊的路徑調整命名。例如:
const store = new Vuex.Store({ modules: { account: { namespaced: true, // 模塊內容(module assets) state: { ... }, // 模塊內的狀態已是嵌套的了,使用 `namespaced` 屬性不會對其產生影響 getters: { isAdmin () { ... } // -> getters['account/isAdmin'] }, actions: { login () { ... } // -> dispatch('account/login') }, mutations: { login () { ... } // -> commit('account/login') }, // 嵌套模塊 modules: { // 繼承父模塊的命名空間 myPage: { state: { ... }, getters: { profile () { ... } // -> getters['account/profile'] } }, // 進一步嵌套命名空間 posts: { namespaced: true, state: { ... }, getters: { popular () { ... } // -> getters['account/posts/popular'] } } } } } })
若是你但願使用全局 state 和 getter,rootState 和 rootGetter 會做爲第三和第四參數傳入 getter,也會經過 context 對象的屬性傳入 action。
若須要在全局命名空間內分發 action 或提交 mutation,將 { root: true } 做爲第三參數傳給 dispatch 或 commit 便可。
要想使模塊內的getter, mutation,action註冊在模塊命名空間,必須在模塊內加上 namespaced: true
使用命名空間在調用action時必須使用
this.$store.dispatch('hero1/getHeroInfo'); computed: { doneTodosCount () { return this.$store.getters['hero1/doneTodos'][0].item; } },