我们知道, Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。
这个状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。
对于state数据源的处理,分为两种类型的操作:
- mutations. mutations方法内可直接修改state数据源,相当于setter方法,但这些方法内不允许执行异步操作。
- getters. 用于获取一些基于state数据源的计算值。getters方法只能读取state数据源的值,不能修改state数据源。
vuex整体大致架构如下:
可以看出,整个流程是单向的、闭环的。这符合状态管理模式的特点。
1.Action
Action的作用与Mutations类似,但它与Mutations有如下区别:
- Action修改数据源是通过commit Mutations的方式来实现
- Action支持执行异步操作
一个简单的action示例如下:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
2.Action函数回调
在某些情况下,我们可能需要在action执行完成后做一些操作,那么就要在action执行完成后,回调一个函数回来。那么,你可能会想着在payload里面添加一个回调函数的变量,如下:
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!")
}
})
通过这种方式回调函数虽然会执行,但是会存在如下问题:
- 如果commit mutation中包含payload变量的属性,且该属性是一个对象列表,那么mutation可能获取不到commit过来的变量或者结果不对,如下:
const store = new Vuex.Store({
state: {
count: 0,
list: []
},
mutations: {
increment ({state}, index) {
// list的内容可能跟你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时数据会出错。那么又该怎么实现函数回调呢,vuex官方文档中提供了解决方案:
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
现在你可以:
store.dispatch('actionA').then(() => {
// ...
})