我們知道卿堂, Vuex 是一個專為 Vue.js 應用程序開發(fā)的狀態(tài)管理模式。
這個狀態(tài)自管理應用包含以下幾個部分:
- state懒棉,驅(qū)動應用的數(shù)據(jù)源草描;
- view,以聲明方式將 state 映射到視圖策严;
- actions穗慕,響應在 view 上的用戶輸入導致的狀態(tài)變化。
對于state數(shù)據(jù)源的處理妻导,分為兩種類型的操作:
- mutations. mutations方法內(nèi)可直接修改state數(shù)據(jù)源逛绵,相當于setter方法,但這些方法內(nèi)不允許執(zhí)行異步操作倔韭。
- getters. 用于獲取一些基于state數(shù)據(jù)源的計算值术浪。getters方法只能讀取state數(shù)據(jù)源的值,不能修改state數(shù)據(jù)源寿酌。
vuex整體大致架構如下:
vuex架構.png
可以看出胰苏,整個流程是單向的、閉環(huán)的醇疼。這符合狀態(tài)管理模式的特點硕并。
1.Action
Action的作用與Mutations類似,但它與Mutations有如下區(qū)別:
- Action修改數(shù)據(jù)源是通過commit Mutations的方式來實現(xiàn)
- Action支持執(zhí)行異步操作
一個簡單的action示例如下:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
2.Action函數(shù)回調(diào)
在某些情況下秧荆,我們可能需要在action執(zhí)行完成后做一些操作倔毙,那么就要在action執(zhí)行完成后,回調(diào)一個函數(shù)回來辰如。那么普监,你可能會想著在payload里面添加一個回調(diào)函數(shù)的變量,如下:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment ({commit}, payload) {
context.commit('increment')
if (payload.success) payload.success()
}
}
})
然后在頁面中dispatch action:
this.$store.dispatch("increment", {
success() {
alert("incremented!")
}
})
通過這種方式回調(diào)函數(shù)雖然會執(zhí)行,但是會存在如下問題:
- 如果commit mutation中包含payload變量的屬性凯正,且該屬性是一個對象列表毙玻,那么mutation可能獲取不到commit過來的變量或者結果不對,如下:
const store = new Vuex.Store({
state: {
count: 0,
list: []
},
mutations: {
increment ({state}, index) {
// list的內(nèi)容可能跟你commit時的結果不一樣
state.list= list
state.count++
}
},
actions: {
increment ({commit}, payload) {
// commit時附帶payload的屬性值
context.commit('increment', payload.index)
if (payload.success) payload.success()
}
}
})
在頁面中dispatch action:
this.$store.dispatch("increment", {
list: [{name: '李白'}, {name: '高漸離'}, {name: '蓋聶'}]
success() {
alert("incremented!")
}
})
因此不要在payload中添加方法屬性廊散,不然commit時數(shù)據(jù)會出錯桑滩。那么又該怎么實現(xiàn)函數(shù)回調(diào)呢,vuex官方文檔中提供了解決方案:
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
現(xiàn)在你可以:
store.dispatch('actionA').then(() => {
// ...
})