一、概念
Vuex
是一个专为 Vue.js
应用程序开发的 状态管理模式。
因为模块间是不共享作用域的,平时用来解决共享参数的方法就是通过组件传参,一旦项目变得很庞大,管理和维护这些值将是相当棘手的事情。
这是我们就可以使用Vuex
集中式存储管理所有组件的状态。
二、整体运作流程
三、使用场景
如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。
四、为啥不使用其他的状态管理器
因为 Vuex
是一个专门为 Vue
应用所设计。这使得它能够更好地和Vue
进行整合,同时提供简洁的 API 和改善过的开发体验。
五、五大核心
State
、Getters
、Mutations
、Actions
、Modules
mapState
、mapGetters
、mapMutations
、mapActions
可以把 Vuex
理解为 “前端的数据库”。state
就是数据库。getters
是用来从数据库取数据的。既然是取,那么肯定是不能修改的,所以, getters
是一个“纯函数”,即不会对元数据造成影响的函数。mutations
是用来修改 state
的。只能是同步操作。actions
可以理解成:我们从后端拿到数据,总得做个处理。处理完了再存到数据库中,当然也可以不处理,就是直接mutation。包含异步操作。
Module :Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割。
mapState
: 当一个组件需要获取多个状态的时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性。
// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'
export default {
// ...
computed: mapState({
// 箭头函数可使代码更简练
count: state => state.count,
// 传字符串参数 'count' 等同于 `state => state.count`
countAlias: 'count',
// 为了能够使用 `this` 获取局部状态,必须使用常规函数
countPlusLocalState (state) {
return state.count + this.localCount
}
})
}
mapState 函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要使用一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给 computed 属性。
computed: {
localComputed () { /* ... */ },
// 使用对象展开运算符将此对象混入到外部对象中
...mapState({
// ...
})
}
mapGetters
辅助函数仅仅是将 store 中的 getter 映射到局部计算属性
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
doneCount: 'doneTodosCount', // 起别名
'anotherGetter',
// ...
])
}
}
Action
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
// context 上下文对象,context.state, context.rootState
context.commit('increment')
}
}
})
// 分发Action, 调用Action
store.dispatch('increment')
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
// 在组件中分发 Action
this.$store.dispatch('xxx')
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
组合Action
处理异步操作,返回Promise
actions: {
actionA ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit('someMutation')
resolve()
}, 1000)
})
}
}
store.dispatch('actionA').then(() => {
// ...
})
利用async/await
// 假设 getData() 和 getOtherData() 返回的是 Promise
actions: {
async actionA ({ commit }) {
commit('gotData', await getData())
},
async actionB ({ dispatch, commit }) {
await dispatch('actionA') // 等待 actionA 完成
commit('gotOtherData', await getOtherData())
}
}
注:一个 store.dispatch 在不同模块中可以触发多个 action 函数。在这种情况下,只有当所有触发函数完成后,返回的 Promise 才会执行。