Vuex是专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
- 适用情况:共享
多个组件依赖于同一状态;
来自不同组件的行为需要变更同一状态。
1. 工作原理
举例: sum += 2
2. 环境搭建
- 安装
npm i vuex
Vue2 中要用 Vuex 的 3 版本npm i vuex@3
,Vue3 中要用 Vuex 的4版本(默认); - 在 src 文件夹中新建 store 文件夹,在 store 文件夹中新建 index.js 文件,然后进行配置:
// 该文件用于创建 Vuex 中最核心的 store
// 引入 Vue 和 Vuex
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
// 1. 准备 actions, 用于响应组件中的动作
const actions = {
yytFunction(context,value){
// context.state.yytData 巴拉巴拉
context.commit('YYTFUNCTION', value);
}
};
// 2. 准备 mutations, 用于操作数据(state)
const mutations = {
YYTFUNCTION(state, value){
// state.yytData 巴拉巴拉 value 巴拉巴拉
}
};
// 3. 准备 state, 用于存储数据(state)
const state = {
yytData: 0
};
// 创建并暴露 store
export default new Vuex.Store({
actions,
mutations,
state
});
- 引入和使用(main.js)
进行了import Vuex from 'vuex'
和Vue.use(Vuex)
这两步后,才能在下一步创建Vue实例对象时,传入store
配置项;
// 引入 vue
import Vue from 'vue';
// 引入 App组件, 它是所有组件的父组件
import App from './App.vue';
// 引入自己创建的 store
import store from './store/index';
// 关闭 Vue 的生产提示
Vue.config.productionTip = false;
new Vue({
el:'#app',
// 将 App 组件放入容器中
render: h => h(App),
store,
beforeCreate(){
Vue.prototype.$bus = this; // 安装全局事件总线
}
})
- 组件中读取vuex中的数据:
this.$store.state.sum
(js脚本里)或$store.state.sum
(<template>
里) - 组件中修改vuex中的数据:
this.$store.dispatch('action中的方法名', 数据)
或this.$store.commit('mutation中的方法名', 数据)
若没有网络请求或其他业务逻辑,组件中也可以越过actions
,即不写dispatch
,直接编写commit
。
2.1. getters配置项
当 state 中的数据需要加工后再使用时,可以用 getters 进行加工。
- 在 index.js 中追加 getters 配置项
// 4. 准备 getters,用于将 state 中的数据进行加工
const getters = {
calData(state){
return state.yytData * 10;
}
}
// 创建并暴露 store
export default new Vuex.Store({
actions,
mutations,
state,
getters
});
- 组件中读取数据
$store.getters.calData
2.2. map方法
mapState()
映射state中的数据为计算属性
computed:{
// 借助 mapState 生成计算属性sum、name,从 state 中读取数据(对象写法)
... mapState({sum:'sum', name:'name'}),
// 借助 mapState 生成计算属性,从 state 中读取数据(数组写法)
... mapState(['sum', 'name'])
}
mapGetters()
映射getters中的数据为计算属性
computed:{
// 借助 mapGetters 生成计算属性bigSum,从 getters 中读取数据(对象写法)
... mapGetters({bigSum:'bigSum'}),
// 借助 mapGetters 生成计算属性bigSum,从 getters 中读取数据(数组写法)
... mapGetters(['bigSum'])
}
mapActions()
生成与 actions 对话的方法,即包含$store.dispatch(xxx)
的函数
methods:{
// 借助 mapMutations 生成对应的方法,方法中会调用 commit 去联系 mutations (对象写法)
...mapMutations({increment:'ADD', decrement:'SUBTRACT'})
}
mapMutations()
生成与 mutations 对话的方法,即包含$store.commit(xxx)
的函数
methods:{
// 借助 mapActions 生成对应的方法,方法中会调用 dispatch 去联系 actions (对象写法)
...mapActions({incrementOdd:'addOdd', incrementWait:'addWait'})
}
使用mapActions
和mapMutations
时如果需要传参,那么在模板中绑定事件时就要传递,否则参数是事件对象。
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数时加</button>
<button @click="incrementWait(n)">等一会儿再加</button>
2.3. 多组件共享数据 - 模块化 & 命名空间
- 目的:让代码更好维护,让多种数据分类更加明确;
- 修改
index.js
,将完成每个功能的配置拆分出来,并开启命名空间
// index.js
import Vue from 'vue';
import Vuex from 'vuex';
import countOptions from './countOptions';
import personOptions from './personOptions';
Vue.use(Vuex);
// 创建并暴露 store
export default new Vuex.Store({
modules:{
c:countOptions,
p:personOptions
}
});
// countOptions.js
export default {
namespaced:true,
actions:{
addOdd(context,value){
if(context.state.sum % 2){
context.commit('ADD', value);
}
},
addWait(context,value){
setTimeout(()=>{
context.commit('ADD', value);
}, 500);
}
},
mutations:{
ADD(state, value){
state.sum += value;
},
SUBTRACT(state, value){
state.sum -= value;
}
},
state:{
sum:0, // 当前的和
name:'kirlant'
},
getters:{
bigSum(state){
return state.sum * 10;
}
}
};
// personOptions.js
import axios from 'axios'
import { nanoid } from 'nanoid';
// 人员列表相关配置
export default {
namespaced:true,
actions:{
addPersonL(context,value){
if(value.name.indexOf('l') === 0){
context.commit('ADD_PERSON', value);
}else{
alert('添加的人要姓l嗷');
}
},
addPersonServer(context){
axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
response=>{
context.commit('ADD_PERSON', {id:nanoid(), name:response.data})
},error=>{
console.log('出错了嗷. ',error);
}
)
}
},
mutations: {
ADD_PERSON(state, value){
state.personList.unshift(value);
}
},
state:{
personList:[
{id:'001', name:'yyt'},
{id:'002', name:'lyl'}
]
},
getters:{
firstPersonName(state){
return state.personList[0].name;
}
}
};
- 开启命名空间后,组件中读取
state
数据:
// 直接读
this.$store.state.c.sum
// 借助 mapState 读
...mapState('c',['sum'])
- 开启命名空间后,组件中读取
getters
数据:
// 直接读
this.$store.getters['p/firstPersonName'];
// 借助 mapGetters读
...mapGetters('p',['firstPersonName'])
- 开启命名空间后,组件中调用
dispatch
// 直接读
this.$store.dispatch('c/addOdd', value);
// 借助 mapActions读
...mapActions('c', {incrementOdd:'addOdd', incrementWait:'addWait'})
- 开启命名空间后,组件中调用
commit
// 直接读
this.$store.commit('p/ADD_PERSON', pObj);
// 借助 mapMutations读
...mapMutations('c', {increment:'ADD', decrement:'SUBTRACT'})