1.概念
专门在vue中实现集中式状态(数据)管理的一个vue插件,对vue应用中多个组件的共享状态进行集中的管理(读/写),
也是组件间的通信方式,且适用于任意组件间通信
2.什么时候用vuex:(共享)
多个组件依赖于同一状态
来自不同组件的行为需求变更同一状态
3.搭建vuex环境
(1).创建文件:src/store/index.js
// 引入vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 使用vuex
Vue.use(Vuex)
// 准备actons--用于响应组件中的动作
const actions = {
// jia(context,value){
// console.log('actions被调用',context,value);
// context.commit('JIA',value)
// },
// jian(context,value){
// console.log('actions被调用',context,value);
// context.commit('JIAN',value)
// },
jianOdd(context,value){
console.log('actions被调用',context,value);
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jianWait(context,value){
console.log('actions被调用',context,value);
setTimeout(() =>{
context.commit('JIA',value)
},1000)
},
}
// 准备mutations--用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations被调用',state,value)
state.sum += value
},
JIAN(state,value){
console.log('mutations被调用',state,value)
state.sum -= value
}
}
// 准备state--用于存储数据
const state = {
sum:0 //当前的求和
}
// 创建 并 暴露store
export default new Vuex.Store({
// actions:actions,
// mutations:mutations,
// state:state
// 简写
actions,
mutations,
state
})
(2).在main.js中创建vm时传入store配置项
// 引入store
import store from './store/index'
new Vue({
el:'#app',
render: h => h(App),
store,
beforeCreate(){
Vue.prototype.$bus = this //安装全局事件总线
}
})
4.关系图
state
顾名思义,所有状态都将被存放在 State 中,类似 Vue 组件中的 data 属性,只不过 State 是面向整个应用,而 data 针对的是单个组件。在 Vue 入口页构造 Vue 实例的时候引入 store 之后,可以在组件中通过 this.$store.state 拿到。
getter
它类似于 Vue 组件中的 computed 计算属性,计算一些需要二次改造的数据。举个例子,我在 Vue 组件中通过 this.$store.state 拿到 State 中的某个数据,但是我需要对这个数据过滤,一个 filter 方法就能拿到过滤后的数据,但是我在很多地方都要使用这个 filter 过滤条件,那么我不断的去复制粘贴(CV 大法),或者将这个 filter 方法抽离到公用函数再引入组件,两种方法都很鸡肋。Getter 为我们解决了这个难题,你可以在 store 中定义 getter 属性,state 数据可作为参数被传入,代码大致如下:
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false },
],
},
getters: {
doneTodos: (state) => {
return state.todos.filter((todo) => todo.done);
},
},
});
在 Vue 组件中便可以通过如下方式进行访问:
this.$store.getters.doneTodos; // [{ id: 1, text: '...', done: true }]
Getter 也可以接收其他的 getters 作为第二个参数:
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length;
};
}
// 使用
store.getters.doneTodosCount; // -> 1
可以通过 mapGetter 将 store 中的 getter 属性映射到局部计算属性内:
import { mapGetters } from 'vuex';
export default {
// ...
computed: {
// 使用对象展开运算符将 getter 混入 computed 对象中
...mapGetters([
'doneTodosCount',
'anotherGetter',
// ...
]),
},
};
在 Vue 组件中便可以直接用 this.doneTodosCount 取到你想要的过滤后的数据。
Mutation
我们修改 State 状态,需要触发一些方法,这些方法就放在 mutations 属性中,mutations 属性中的方法接受 2 个参数,第一个参数是state,内部包含所有状态值。第二个参数为提交载荷(Playload),也就是在外部通过 store.commit 方法触发 mutations 时额外带入的值。代码如下所示:
const store = new Vuex.Store({
state: {
count: 1,
},
mutations: {
increment(state) {
// 变更状态
state.count++;
},
},
});
// 触发
store.commit('increment'); // 参数名称必须对应 mutations 的方法属性值。
//
const store = new Vuex.Store({
state: {
count: 1,
},
mutations: {
increment(state, n) {
state.count += n;
},
},
});
// 带载荷触发
store.commit('increment', 10);
Action
其实 Action 很好理解,它与 Mutation 类似,只不过 Action 是提交 mutation 而不是直接改变状态,并且 Action 被赋予异步的能力,也就是能在里面请求异步数据之后再触发状态的更新。
const store = new Vuex.Store({
state: {
count: 0,
},
mutations: {
increment(state, data) {
state.count += data.length;
},
},
actions: {
async increment(ctx) {
const data = await getData();
ctx.commit('increment', data);
},
},
});
// 分发 Action
store.dispatch('increment');
mapActions 帮我们更好的在页面中分发 Actions(在此之前需要在入口页注入 store):
import { mapActions } from 'vuex';
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy', // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment', // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
}),
},
};
5.基本使用
(1).初始化数据、配置actions、配置mutations,操作文件store.js
// 引入vue
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 使用vuex
Vue.use(Vuex)
// 准备actons--用于响应组件中的动作
const actions = {
jia(context,value){
console.log('actions被调用',context,value);
context.commit('JIA',value)
},
}
// 准备mutations--用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations被调用',state,value)
state.sum += value
},
}
// 准备state--用于存储数据
const state = {
sum:0 //当前的求和
}
// 创建 并 暴露store
export default new Vuex.Store({
// actions:actions,
// mutations:mutations,
// state:state
// 简写
actions,
mutations,
state
})
(2).组件中读取vuex中state的数据:
$store.state.sum
(3).组件中修改vuex中的数据:
this.$store.dispatch('action中的方法名',数据)
或
$store.commit('mutations中的方法名',数据)
备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接写commit
5.getters的使用
(1).概念:当state中的数据需要经过加工后再使用时,可以使用getters加工
(2).在store.js中追加getters配置
//准备getters 用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum * 10
}
// 创建 并 暴露store
export default new Vuex.Store({
。。。。。
getters
})
}
(3).组件中读取数据:
$store.getters.bigSum
6.四个map方法的使用
(1).mapState方法:用于帮助我们映射state中的数据为计算属性
computed:{
// 借助mapState生成计算属性,从state中读取数据(对象写法)
...mapState({he:'sum',name:'name',xueke:'subject'}),
// 借助mapState生成计算属性,从state中读取数据(数组写法)
...mapState(['sum','name','subject']),
}
(2).mapGetters方法:用于帮助我们映射getters中的数据为计算属性
computed:{
// 借助mapGetters生成计算属性,从Getters中读取数据(对象写法)
// ...mapGetters({bigSum:'bigsum'})
// 借助mapGetters生成计算属性,从Getters中读取数据(数组写法)
...mapGetters([bigSum])
}
(3).mapActions方法:用于帮助我们映射actions中的数据为计算属性 即:包含$store.dispath(xxx)函数
methods: {
/* addOdd(){
this.$store.dispatch('jianOdd',this.n)
},
addWait(){
this.$store.dispatch('jianWait',this.n)
} */
// 借助mapActions生成对应的方法,方法中会调用dispatch去联系action(对象方法)
...mapActions({addOdd:'jianOdd',addWait:'jianWait'}),
// 借助mapActions生成对应的方法,方法中会调用dispatch去联系action(数组方法)
// ...mapActions(['jianOdd','jianWait']) 两个名字相同
},
(4).mapMutations方法:用于帮助我们映射mutations中的数据为计算属性 即:包含$store.commit(xxx)函数
methods: {
/* increment(){
// this.$store.dispatch('JIA',this.n)
this.$store.commit('JIA',this.n)
},
subtract(){
// this.$store.dispatch('JIAN',this.n)
this.$store.commit('JIAN',this.n)
}, */
// 借助mapMutations生成对应的方法,方法中会调用commit去联系mutation(对象方法)
...mapMutations({increment:'JIA',subtract:'JIAN'}),
// 借助mapMutations生成对应的方法,方法中会调用commit去联系mutation(数组方法)
// ...mapMutations(['JIA','JIAN']),
}
7.模块化+命名空间
(1).目的:让代码更好维护,让多种数据分类更加明确
(2).修改store.js
const countAbout={
namespaced:true, //开启命名空间
actions:{},
mutations:{},
state:{},
getters:{}
}
const personAbout={
namespaced:true, //开启命名空间
actions:{},
mutations:{},
state:{},
getters:{}
}
// 创建 并 暴露store
export default new Vuex.Store({
modules:{
countAbout:countOptions,
personsAbout:peronsOptions
}
})
(3).开启命名空间后,组件中读取state数据
方式一:自己直接读取
this.$store.state.personAbout.list
方式二:借助mapState读取
...mapState('countAbout',['sum','name','subject'])
(4).开启命名空间后,组件中读取getters
方式一:自己直接读取
this.$store.getters[personAbout/firstPersonName]
方式二:借助mapGetters读取
...mapGetters('personsAbout',['firstPersonName'])
(5).开启命名空间后,组件中调用dispatch
方式一:自己直接dispatch
this.$store.dispatch('personsAbout/addPersonWang',personObj)
方式二:借助mapActions
...mapActions('countAbout',{addOdd:'jianOdd',addWait:'jianWait'})
(6).开启命名空间后,组件中调用commit
方式一:自己直接commit
this.$store.commit('personsAbout/ADD_Persons',personObj)
方式二:借助mapMutations
...mapMutations('countAbout',{increment:'JIA',subtract:'JIAN'})