Vuex是一个专门为Vue.js应用程序开发的数据状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
优点
1.数据仓库: 集中式存储
2.组件通信: 便于在各个组件之间进行数据共享、传递
3.单项数据流: 遵循特定的规则,特定的入口改变数据,特定的出口输出数据,同时可监测到数据的变化过程
Vue有五个核心概念:state, getters, mutations, actions, modules。
1.state => 基本数据
2.getters => 从基本数据派生的数据
3.mutations => 提交更改数据的方法,同步!
4.actions => 像一个装饰器,包裹mutations,使之可以异步。
5.modules => 模块化Vuex
State
state即Vuex中的基本数据!(可以理解成 vue 组件里的某些 data )
单一状态树
Vuex使用单一状态树,即用一个对象就包含了全部的状态数据。state作为构造器选项,定义了所有我们需要的基本状态参数。
在Vue组件中获得Vuex属性
我们可以通过Vue的Computed获得Vuex的state,如下:
1.创建store仓库,并在vue中挂载
// src/store/index.js
import Vuex from 'vuex'
import Vue from 'vue'
Vue.use(Vuex)
const store = new Vuex.Store({
// 声明在仓库中的数据
state: {
number: 1
}
})
export default store
2.在main.js中引用
// src/main.js
import store from '@/store'
new Vue({
// ...
store
})
3.在组件中使用state数据
vuex通过computed计算属性监测数据的变化,进而影响到所有组件中数据的状态
计算属性中使用this.$store.state获取
computed: {
number () {
return this.$store.state.number
}
}
借助辅助函数mapState实现
// 组件内引入mapState
import { mapState } from 'vuex'
computed: {
...mapState([
'number'
])
}
4.在store.js文件中定义mutations,编写函数plus()用于改变或操作state的值,于是就引入了matations
mutations
提交mutation是更改Vuex中的store中的状态的唯一方法。
mutation必须是同步的,如果要异步需要使用action。
每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。(提交荷载在大多数情况下应该是一个对象),提交荷载也可以省略的。
new Vuex.Store({
// ...
mutations: {
plus (state) {
state.number++
}
}
})
5.那如何调用store里面mutations属性里的plus方法呢?
有两种方法:第一种是this.$store.commit(‘函数名’),他会直接去找mutations里面的函数;第二种方法是引入mapMutations函数,那什么是mapMutations函数呢?
mapMutations 辅助函数
与其他辅助函数类似,你可以在组件中使用 this.$store.commit(‘xxx’) 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
<script>
import { mapState, mapMutations } from 'vuex'
export default {
name: 'A',
computed: {
...mapState([
'number'
])
},
methods: {
// 返回需要的mutations函数,方法2需要用到
...mapMutaions([
'plus'
]),
plusNumber () {
// 方法1. 可以直接通过store提交mutations,只需这一步即可
// 此处plus是mutations中的方法
this.$store.commit('plus')
// 方法2. 也可以使用mapMutations辅助函数调用,但需要返回需要的mutations函数才能直接这样写:this.plus()
this.plus()
}
}
}
</script>
6.除了在mutations里编写函数plus(),还能再actions里编写
## actions
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
new Vuex.Store({
// ...
actions: {
plus (state) {
state.number++
}
}
})
调用:跟调用mutation里的函数一样,只是把commit换成dispatch而已
this.$store.dispatch('plus')
小结一下:
dispatch:含有异步操作,例如向后台提交数据,写法:
this.$store.dispatch('action方法名',值)
commit:同步操作,写法:
this.$store.commit('mutations方法名',值)
getters
即从store的state中派生出的状态。
getters接收state作为其第一个参数,接受其他 getters 作为第二个参数,如不需要,第二个参数可以省略如下例子:
new Vuex.Store({
// ...
getters: {
// 单个参数
countDouble: function(state){
return state.count * 2
},
// 两个参数
countDoubleAndDouble: function(state, getters) {
return getters.countDouble * 2
}
}
})
与state一样,我们也可以通过Vue的Computed获得Vuex的getters。
computed: {
count: function(){
return this.$store.state.count
},
countDouble: function(){
return this.$store.getters.countDouble
},
countDoubleAndDouble: function(){
return this.$store.getters.countDoubleAndDouble
}
}
同样,Getters也有辅助函数
mapGetters 辅助函数
mapGetters 辅助函数仅仅是将 store 中的 getters 映射到局部计算属性,与state类似
注意:getters可以对state进行计算操作!计算后返回state,但最好不要对state数据进行更改,要更改的话请使用mutations或actions属性。(可参考:Vuex之理解Getters的用法)
import { mapGetters } from 'vuex'
export default {
// ...
computed: {
// 使用对象展开运算符将 getters 混入 computed 对象中
...mapGetters([
'countDouble',
'CountDoubleAndDouble',
//..
])
}
}
如果你想将一个 getter 属性另取一个名字,使用对象形式:
mapGetters({
// 映射 this.double 为 store.getters.countDouble
double: 'countDouble'
})
Modules
使用单一状态树,导致应用的所有状态集中到一个很大的对象。但是,当应用变得很大时,store 对象会变得臃肿不堪。
为了解决以上问题,Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割:
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 的状态
模块的局部状态
对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态,对于模块内部的 getter,根节点状态会作为第三个参数:
const moduleA = {
state: { count: 0 },
mutations: {
increment (state) {
// state 模块的局部状态
state.count++
}
},
getters: {
doubleCount (state) {
return state.count * 2
},
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}
同样,对于模块内部的 action,context.state 是局部状态,根节点的状态是 context.rootState:
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum (context) {
if ((context.state.count + context.rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}