Vuex是专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读写),也是一种组件间通信的方式,且适用于任意组件间通信。
直白点说就是多个组件需要对同一个数据进行变更时可以使用vuex,更方便一些。
下图是vuex的工作模式。
配置vuex环境
安装vuex npm i vuex@3 vue2使用vuex3
然后创建一个src/store/index.js文件
// 引入Vue核心库
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 应用Vuex插件
Vue.use(Vuex)
// 准备actions 用于响应组件动作
const actions = {}
// 准备mutations 用于操作数据(state)
const mutations = {}
// 准备state 用于存储数据
const state = {}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
main.js文件中引入index.js文件,配置store。
import Vue from 'vue'
import App from './App'
// 引入index.js文件
import store from './store/index.js'
// 关闭生产提示
Vue.config.productionTip = false;
// 创建Vue实例
new Vue({
el: '#app',
render: h => h(App),
store
})
基本使用
初始化数据、配置actions、mutations,操作文件stroe.js。
// 创建Store
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
// 应用插件
Vue.use(Vuex);
// 创建actions 用于响应组件中的动作
const actions = {
addOdd(content, value){
if(content.state.sum % 2){
content.commit('ADDODD', value);
}
},
addWait(content, value){
setTimeout(()=>{
content.commit('ADDWAIT', value);
}, 1000)
}
};
// 创建mutations 用于操作数据
const mutations = {
ADD(state, value){
state.sum += value;
},
MIN(state, value){
state.sum -= value;
},
ADDODD(state, value){
state.sum += value;
},
ADDWAIT(state, value){
state.sum += value;
}
};
// 创建state 用于存储数据
const state = {
sum: 0
};
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
});
getters的使用
当state中的数据需要经过加工后再使用时,可以使用getters配置项进行加工。
在store/index.js文件中添加getters配置。
......
// 创建getters 用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum * 10;
}
}
// 创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
});
组件中通过$store.getters读取数据。
<h1>当前求和放大10倍:{{ $store.getters.bigSum }}</h1>
四个map方法的使用
使用vuex展示数据时,前缀过长,所以我们可以通过计算属性获得state中的数据。
computed: {
sum(){
return this.$store.state.sum;
},
bigSum(){
return this.$store.getters.bigSum;
},
school(){
return this.$store.state.school;
},
subject(){
return this.$store.state.subject;
}
},
但是上述传统方法会使得代码冗余,重复代码较多,所以我们可以通过vuex提供的四个map方法帮助我们更好的获得数据,注意要先引入这些方法。
import {mapState, mapGetters, mapActions, mapMutations} from 'vuex';
mapState()方法 用于帮助我们映射state中的数据为计算属性
computed: {
// 借助mapState方法生成计算属性(对象写法)
...mapState({sum: 'sum', school: 'school', subject: 'subject'})
// 借助mapState方法生成计算属性(数组写法),仅限于属性名和state中的数据名相同
...mapState(['sum', 'school', 'subject'])
},
mapGetters()方法 用于帮助我们映射getters中的数据为计算属性
computed: {
// 借助mapGetters方法生成计算属性(对象写法)
...mapGetters({bigSum: 'bigSum'})
// 借助mapGetters方法生成计算属性(数组写法),仅限于属性名和state中的数据名相同
...mapGetters([bigSum])
},
mapActions()方法 用于帮助我们生成与actions对话的方法,包含$store.dispatch(xxx)的函数。
computed: {
// 借助mapActions方法生成计算属性(对象写法)
...mapActions({incrementOdd: 'addOdd', incrementWait: 'addWait'}),
// 借助mapActions方法生成计算属性(数组写法),仅限于方法名和actions中的方法名相同。
...
},
mapMutations()方法 用于帮助我们生成与mutations对话的方法,包含$store.commit(xxx)的函数。
computed: {
// (对象写法)
...mapMutations({increment: 'ADD', decrement: 'MIN'}),
// (数组写法)
...
},
注意:mapActions()和mapMutations()方法生成的函数,如果需要传递参数,在模板中绑定事件时就要传递,否则默认参数是事件对象Event。
<button @click="decrement(n)">-</button>
<button @click="increment(n)">+</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
vuex模块化
vuex模块化是为了让代码更好维护,让多种数据分类更加明确。
新建一个./store/count.js文件用于配置求和组件使用到的数据,注意要配置namesspaced属性,用于开启命名空间。
export default {
namespaced: true,
state: {
sum: 0,
school: '尚硅谷',
subject: '前端',
},
getters: {
bigSum(state){
return state.sum * 10;
}
},
actions: {
addOdd(content, value){
if(content.state.sum % 2){
content.commit('ADDODD', value);
}
},
addWait(content, value){
setTimeout(()=>{
content.commit('ADDWAIT', value);
}, 1000)
}
},
mutations: {
ADD(state, value){
console.log(value);
state.sum += value;
},
MIN(state, value){
state.sum -= value;
},
ADDODD(state, value){
state.sum += value;
},
ADDWAIT(state, value){
state.sum += value;
},
}
}
在./store/index.js文件中引入count.js模块,并且在暴露store时要使用modules属性配置模块,就像是父组件使用components配置子组件一样。
// 创建Store
import Vue from 'vue';
// 引入vuex
import Vuex from 'vuex';
import countOptions from './count';
// 应用插件
Vue.use(Vuex);
// 创建并暴露store
export default new Vuex.Store({
// 配置模块
modules: {
countOptions
}
});
开启命名空间后读取数据或者调用dispatch、commit时与之前是有一些区别的。、
- 读取
state数据。
// 方式一:自己直接读取
this.$store.state.countOptions.sum
// 方式二:借助mapState读取
...mapState('countOptions',['sum', 'school', 'subject']),
- 读取
getters数据。
// 方式一:自己直接读取
this.$store.getters['countOptions/bigSum]
// 方式二:借助mapGetters读取
...mapGetters('countOptions', ['bigSum']),
- 调用
dispatch。
// 方式一:自己直接调用dispatch
this.$store.dispatch('countOptions/addPersonWang', this.n);
// 方式二:借助mapActions读取
...mapActions('countOptions',{incrementOdd: 'addOdd', incrementWait: 'addWait'}),
- 调用
commit。
// 方式一:自己直接调用commit
increment(){
return this.$store.commit('countOptions/ADD', this.n);
}
// 方式二:借助mapMutations读取
...mapMutations('countOptions', {increment: 'ADD', decrement: 'MIN'})