Vue2 - Vuex
1.Vuex简介
概念:专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方 式,且适用于任意组件间通信。
Github 地址: https://github.com/vuejs/vuex
为什么需要这么一个Vuex插件呢?例如我现在有这么一种场景:
如上图所示:我现在App下管理这众多组件,有A、B、D,B下面又有组件C,现在我A中有数据x为1,y为2,现在我想要BCD组件都能够读取到x的内容,所以使用全局事件总线来完成,对应途中红色的。此时还好,只有4条线,现在如果我BCD组件又都要修改x的值呢,ok,继续使用全局事件总线,对应图中的绿色部分,此时又有4条线了。
可见对于1个数据的读取和修改,只要组件一多,维护起来就很困难了,十分混乱,所以,对于x这种很多组件都想要进行读写操作的数据,那么我们可以将他提升为共享数据,对应下图:
将共享数据x存放到Vuex中,这样所有组件读写都很方便。而且很清晰,不混乱。
上图中的双箭头表示可读可写。
2. 求和案例-Vue纯享版
了解了Vuex的概念之后,先着急来看Vuex的实现,我们用一个案例来引出Vuex。
案例:计算求和,可加可减、以及奇数加、等一会加等功能。
创建Count组件:
<template>
<div>
<h3>当前求和为:{{ sum }}</h3>
<select v-model.number="step">
<option value="1">1</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前和为奇数在加</button>
<button @click="incrementWait">等500ms在加</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
sum: 0,//求和的值
step: 1 //需要操作的步数
}
},
methods:{
increment(){
this.sum += this.step;
},
decrement(){
this.sum -= this.step;
},
incrementOdd(){
if (this.sum % 2 !== 0){
this.sum += this.step;
}
},
incrementWait(){
setTimeout(()=>{
this.sum += this.step;
},500);
}
}
}
</script>
<style scoped>
button{
margin-left: 10px;
}
</style>
App组件:
<template>
<div class="container">
<Count></Count>
</div>
</template>
<script>
import Count from "@/components/Count.vue";
export default {
name: 'App',
components: {Count},
}
</script>
<style>
.container {
display: flex;
justify-content: space-around;
}
</style>
执行结果:
其中的具体功能你可以自行测试。待会我们就使用Vuex来改造这个案例。
3. Vuex工作原理
Vuex的原理图:
上图中的Actions、Mutations、State其实就是普通的Object类型的对象。
就拿第二小节中的例子和这个图对应起来讲解。
上图中的Vue Component
对应Count
组件,就拿加法来说,当你想要使用Vuex来操作共享的数据的时候,你首先需要从Vue Component
出发,然后调用dispatch
这个API,表示分发,这个API可以接收两个参数,第一个参数表示你要执行的动作,例如加法,第二个参数传递值,例如加2,对应的dispatch
就是:dispatch('jia',1)
;当你调用了dispatch
方法之后,就来到了Vuex
中的Actions
部分,在这部分中,并没有真正执行加法这个操作,而是调用commit
这个API,表示提交,这个API也可以接收两个参数,和dispatch
一样,第一个参数表示要执行的动作,第二个参数传递值,调用了这个commit
这个API之后,就来到了Vuex
中的Mutations
部分,在这部分才是真正执行加法操作的,在这个阶段中,他会按照commit
传递过来数据进行操作,不过它首先会读取State
部分的数据,然后执行Mutate
操作,将数据改变了之后又存放到Sate部分中去,这就是整个的执行逻辑了。
上诉描述对应的图:
其实看完Vuex
的工作原理之后,其实会有这样的感觉,就感觉Actions
部分挺多余的,为什么不直接从Vue Component
到达Mutations
部分呢?他就好像在这里就只是简单传递了一下,并没有怎么去执行操作,其实不然。你能从图中看到有两个地方能够到达Actions
部分,一个是调用dispatch
这个API之后,一个是Backend API
,这个后端接口,当你dispatch
只传递执行的动作的时候,但是值是需要从后端接口来获取的时候,这个时候你就不能绕开Actions
直达Mutations
了,因为只有在Actions
这里才能和后端接口打交道,所以Actions
是必不可少的,但是也允许你直接从Vue Component
到达Mutations
,只是说特定的场景下不能绕过Actions
。
注意:上图中的Vuex好像包括了Actions、Mutations、State这三部分,不过,还有一个很重要的东西没有在上图显示出来,那就是store,是由store来管理Actions、Mutations、State这三部分
就比如上述的dispatch这个API,不是window提供的,而是store提供的。
4. 搭建Vuex环境
安装
Vuex
在Vue2中,只能安装Vuex3,不能安装Vuex4,Vuex4只能Vue3使用
npm i vuex@3.6.2
使用
Vuex
因为Vuex是插件,所以要按照插件的使用方式来使用它:
import Vuex from 'vuex' Vue.use(Vuex)
创建
store
因为Actions、Mutations、State这三部分这三部分都是由store来管理的,所以你要创建store。
创建store的时候,我们一般的规范是:
- 在
src
下创建store文件
夹 - 在
store
下创建index.js
项目结构:
在
index.js
文件中,来创建store
:- 引入
Vuex
,在第二步中,我写出了引入Vuex
的方式 - 创建
Actions
、Mutations
、State
这三个对象 - 使用
Vuex
创建store
,并且暴露出去
index.js
:import Vue from "vue"; import Vuex from 'vuex' //使用Vuex Vue.use(Vuex); //创建三个部分 const actions = {}; const mutations = {}; const state = {}; //创建store const store = new Vuex.Store({ actions:actions, mutations:mutations, state:state }); //暴露store export default store;
注意:这上面部分有一些可以简写:
import Vue from "vue"; import Vuex from 'vuex' //使用Vuex Vue.use(Vuex); //创建三个部分 const actions = {}; const mutations = {}; const state = {}; //创建并暴露store export default new Vuex.Store({ actions, mutations, state });
- 在
在
main.js
入口文件中引入store
下的index.js
import Vue from 'vue' import App from './App.vue' import store from "@/store"; Vue.config.productionTip = false new Vue({ components:{ App }, render: createElement => createElement(App), beforeCreate() { Vue.prototype.$bus = this; }, store, //配置store,这里使用了简写形式,完整的 store:store,键值相同时可简写 mounted() { console.log(this) //vm上的查看一下store } }).$mount('#app')
可见这上面就有我们的
dispatch
、commit
等API。
注意:必须在store下的index.js中明确引入Vuex,不能再main.js中引入Vuex,否则报错:必须先引入Vuex才可创建store实例。这是因为在脚手架执行js文件的时候,会先扫描所有的import语句,并且进入对应的js文件执行完毕之后,才执行其他代码。
例如如下的执行顺序:
import A from 'A' console.log(111); console.log(222); import B from 'B'
执行顺序为:先执行A、B中的js代码,之后再执行两个console.log。
并且将store配置到Vue实例身上之后,所有的组件实例对象也可以看见:
在Count组件查看一下组件实例对象:
mounted() {
console.log('Count组件...',this);
}
这下Vue实例和组件实例对象就都能够使用Vuex了。
5. 求和案例-Vuex版
5.1 案例改造
这里我们将之前的Vue纯享版的求和按钮进行更改,改为Vuex版本。这里目前就只有Count组件,还无法体现共享这个概念,不过先不着急,咋们先这个改,主要来练练Vuex的流程。
严格按照下图流程来编写:
首先将公共的sum,因为我们都是在读写sum数据,所以他是公共的。移动到Vuex的State对象中,因为他是存放数据的:
const state = {
sum: 0,//求和的值
};
将之前写的方法里面的业务逻辑也要先移动到Action对象中,并且原来methods
中的方法要用dispatch
API来传递数据了。
之前的increment
方法:
increment(){
this.$store.dispatch('jia',this.step);
},
increment
调用了dispatch
这个API之后,就会将jia
这个操作以及值传递给Vuex中的Actions对象:
const actions = {
jia(context,value){
console.log('Actions中的jia执行了',context,value);
}
};
每一个actions
中的方法都可以接收两个参数:
- 上下文对象
- 传递过来的值
我们来输出看看:
可见第一个上下文对象里面有很多东西,比如我们已经熟悉的commit
、dispatch
、state
等,还有一些其他的,这些参数后面再说;第二个参数就将值传递过来了。
按照Vuex的流程,现在就要从Actions走到Mutations这个部分:
const actions = {
jia(context,value){
console.log('Actions中的jia执行了',context,value);
context.commit('JIA',value); //调用commit 走到Mutaions部分
}
};
const mutations = {
JIA(state,value){
console.log('Mutations中的JIA执行了',state,value);
state.sum += value;
}
};
可见在Actions
部分的时候,你只需要调用上下文对象中的commit
这个API就可以来到Mutations
部分。一般来说,我们对于Actions部分的方法写为小写,Mutations中的方法写为大写,这样容易区分。并且在Mutations部分才是真正操作数据的,在其他部分最好不要操作数据。
在Mutations部分中的所有方法都可以接收到两个参数:
- state对象
- 传递的值
我们输出来看看:
可见State中也为每个数据匹配了getter和setter,这样就能够被Vue给监视了。
现在整个加的流程已经跑通了,在Count组件中,渲染数据的时候,在插值语法模块中不能直接写sum,而是$store.state.sum
,这里不多说。
现在将其他方法给补齐,给出的完整代码为:
Count.vue
:
<template>
<div>
<h3>当前求和为:{{$store.state.sum}}</h3>
<select v-model.number="step">
<option value="1">1</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前和为奇数在加</button>
<button @click="incrementWait">等500ms在加</button>
</div>
</template>
<script>
export default {
name: "Count",
data() {
return {
step: 1 //需要操作的步数
}
},
methods:{
increment(){
this.$store.dispatch('jia',this.step);
},
decrement(){
this.$store.dispatch('jian',this.step);
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.step);
},
incrementWait(){
this.$store.dispatch('jiaWait',this.step);
}
},
mounted() {
//console.log('Count组件...',this);
}
}
</script>
<style scoped>
button{
margin-left: 10px;
}
</style>
store
文件夹下的index.js
:
import Vue from "vue";
import Vuex from 'vuex'
//使用Vuex
Vue.use(Vuex);
//创建三个部分
const actions = {
jia(context,value){
console.log('Actions中的jia执行了',context,value);
context.commit('JIA',value);
},
jian(context,value){
console.log('Actions中的jian执行了',context,value);
context.commit('JIAN',value);
},
jiaOdd(context,value){
if (context.state.sum % 2 !== 0){
console.log('Actions中的jiaOdd执行了',context,value);
context.commit('JIA',value); //这里调用JIA就可以了,不用在Mutations中再重复写了
}
},
jiaWait(context,value){
setTimeout(()=>{
console.log('Actions中的jiaWait执行了',context,value);
context.commit('JIA',value); //这里调用JIA就可以了,不用在Mutations中再重复写了
},500);
},
};
const mutations = {
JIA(state,value){
console.log('Mutations中的JIA执行了',state,value);
state.sum += value;
},
JIAN(state,value){
console.log('Mutations中的JIA执行了',state,value);
state.sum -= value;
}
};
const state = {
sum: 0,//求和的值
};
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
});
注意看我上面Count组件中的methods中的方法,之前的什么判断逻辑啥的以及定时器啥的全部没有写在这里了,而是移动到了Actions部分,因为我们讲解Vuex原理的时候说了,在Actions部分,写业务逻辑以及发送请求到后端请求数据。
由于我们之前说了,如果没有其他的业务逻辑或者请求后端数据,那么你是可以直接从Vue Component
调用commit
这个API到Mutations
部分的,所以我们可以继续改造我们的Count
组件和index.js
:
Count
组件的methods
部分:
methods:{
increment(){
this.$store.commit('JIA',this.step);//没有其他业务逻辑,可以改为commit,直接到Mutations部分去
},
decrement(){
this.$store.commit('JIAN',this.step);//没有其他业务逻辑,可以改为commit,直接到Mutations部分去
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.step);
},
incrementWait(){
this.$store.dispatch('jiaWait',this.step);
}
},
index.js
中部分修改:
const actions = {
jiaOdd(context,value){
if (context.state.sum % 2 !== 0){
console.log('Actions中的jiaOdd执行了',context,value);
context.commit('JIA',value); //这里调用JIA就可以了,不用在Mutations中再重复写了
}
},
jiaWait(context,value){
setTimeout(()=>{
console.log('Actions中的jiaWait执行了',context,value);
context.commit('JIA',value); //这里调用JIA就可以了,不用在Mutations中再重复写了
},500);
},
};
const mutations = {
JIA(state,value){
console.log('Mutations中的JIA执行了',state,value);
state.sum += value;
},
JIAN(state,value){
console.log('Mutations中的JIA执行了',state,value);
state.sum -= value;
}
};
const state = {
sum: 0,//求和的值
};
可见可以将Actions
部分中jia
和jian
部分方法删除,因为由于没有其他复杂的逻辑,而是直接操作数据的,所以Vue Component
直接和Mutations
对话了,但是由于其他的方法有其他的业务逻辑,例如if判断、定时器等,所以不能由Vue Component
直接和Mutations
对话。
5.2 疑惑解答
我在Count组件本来就可以获取到State对象,为啥不在methods中直接操作数据呢?
这里就涉及到封装的问题了,如果在methods中要操作的这个state很复杂,要经过很多步骤才能够得到预期的state,例如这个state中的某个数据要先经过加,再经过乘法,再经过取模,在经过减法…..很多步骤,我们把这些操作取个名:
getExpectData
。如果你直接写在了methods中,今后,其他组件凡是想要执行
getExpectData
的时候都需要重写一遍逻辑,这就显然没必要了,我们为啥不直接将这个很复杂的操作写在Vuex中呢?这样大家所有的组件都能再想要执行getExpectData操作的时候调用一下即可。还有一个原因就是操作数据(State)一般都写在了Mutations部分,因为Vuex的开发者工具是直接和Mutations部分对话的,你写在其他部分开发者工具是看不见的。
在Actions中,传递的Context上下文对象中为啥还有dispatch?
这是因为有可能Actions中某个方法由很多业务逻辑,如果全写在一个方法中,就显得这个方法很长,难以维护,所以你可以再在Actions中写一些其他的方法,然后其中一个方法中使用dispatch来调用Actions的其他方法,这样,你的主要的方法中代码就很少了,把不同的业务封装到了Actions的其他方法中去了。
5.3 Vuex开发者工具
由于Vuex是由Vue出品的,所以Vuex的开发者工具也是vue.js.devtools
。
当Vue检测到你有Vuex之后,开发者工具显示如下:
并且,你可以看到你的每一次操作,比如我点击了等500ms在加:
在Actions中,你能看见具体的数据。
在Mutaions中也能看见具体的数据。
6. Vuex中getters配置项
之前我们知道,Vuex中包含3部分:Actions
、Mutations
、State
。本小节要讲解Vuex另外一个配置项:getters
。
那什么时候使用getters这个配置项呢?当state中的数据需要经过加工后再使用时,可以使用getters加工。
可能有人会有这样的疑惑:数据加工我可以使用计算属性Computed来加工呀,为啥非要用getters这个配置项呢?
其实计算属性加工之后的数据,只能是本组件自己使用,其他组件想用是没有办法复用的,必须又得重写在写一遍,所以getters还是有用的。
现在需求:对于之前的求和案例:
配置步骤:
在store文件夹下的index.js文件中定义
getters
并且配置到store
上去://定义getters const getters = { boostSum(state) {//放大10倍后的值 return state.sum * 10; } }; //创建并暴露store export default new Vuex.Store({ actions, mutations, state, getters });
注意:
- getters对象中,只能配置函数,函数能够接收一个参数,就是State,这个函数中做的事情就是你要加工的逻辑,并且最后要返回(return)。
- 定义了getters对象之后,一定要配置到Store上面去,否则无效。
在组件中使用:
使用格式:
$store.getter.函数名
。改造
Count
组件代码:<template> <div> <h3>当前求和为:{{$store.state.sum}}</h3> <h4>当前求和放大10倍为:{{$store.getters.boostSum}}</h4> <select v-model.number="step"> <option value="1">1</option> <option value="5">5</option> <option value="10">10</option> </select> <button @click="increment">+</button> <button @click="decrement">-</button> <button @click="incrementOdd">当前和为奇数在加</button> <button @click="incrementWait">等500ms在加</button> </div> </template>
可见我使用的时候就是
$store.getters.boostSum
。结果:
执行没问题。
现在代码没问题了,我想要看看getters到底是啥,输出看看:
7. Vuex中四种Map方法
我现在的需求如下:
改造index.js,加上学校和学生:
const state = {
sum: 0,//求和的值
student: '念心卓',
school: 'B站大学'
};
改造Count组件:
<template>
<div>
<h3>当前求和为:{{$store.state.sum}}</h3>
<h4>当前求和放大10倍为:{{$store.getters.boostSum}}</h4>
<h4>学生{{$store.state.student}}就读于{{$store.state.school}}</h4>
<select v-model.number="step">
<option value="1">1</option>
<option value="5">5</option>
<option value="10">10</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前和为奇数在加</button>
<button @click="incrementWait">等500ms在加</button>
</div>
</template>
效果如下:
现在我们来观察代码:
可见,在插值语法中,出现了大量的$store.state.xxx
,一个还好,多了就有点混乱了,而且Vue官方也建议我们在插值语法中尽量写的简单。
所以,这里我们可以使用计算属性来简单改造一下:
<template>
<div>
<h3>当前求和为:{{getSum}}</h3>
<h4>当前求和放大10倍为:{{$store.getters.boostSum}}</h4>
<h4>学生{{getStudent}}就读于{{getSchool}}</h4>
<!--省略其他结构-->
</div>
</template>
<script>
export default {
name: "Count",
//省略data、methods等其他代码
computed:{
getSum(){
return this.$store.state.sum;
},
getStudent(){
return this.$store.state.student;
},
getSchool(){
return this.$store.state.school;
}
}
}
可见使用计算属性之后,插值语法中简洁了不少;但是你的插值语法简洁了,你的计算属性由冗余了:
那是否能够再次简洁一下上面的代码呢?只要我传递不一样的函数名称和state属性就可以了呢?
这时候Vuex中mapState就要登场了。
7.1 mapState
mapState
,顾名思义就是State的映射,他的出现正是解决上诉情况的:用于帮助我们映射state
中的数据为计算属性
使用步骤:
引入Vuex中的mapState:
import {mapState} from "vuex";
在计算属性中使用它:
computed:{ /*getSum(){ return this.$store.state.sum; }, getStudent(){ return this.$store.state.student; }, getSchool(){ return this.$store.state.school; }*/ ...mapState({getSum:'sum',getStudent:'student',getSchool:'school'}), }
注意看我上面的代码,我mapState使用了展开运算符,且是必须使用展开运算符。一使用展开运算符,你就明白,
mapState({getSum:'sum',getStudent:'student',getSchool:'school'})
这一串其实是一个对象,我们来看看它到底是什么对象,并且看看里面有什么属性:mounted() { console.log('Count组件...',mapState({getSum:'sum',getStudent:'student',getSchool:'school'})); }
可见,键就是我上面写的:
getSum,getStudent,getSchool
;值就是一个个mappedState函数,但是我上面明明写的是:sum、student、shcool
,这就是mapState的做的事情了,无需过多关心。测试成功
所以总的来说,使用mapState的时候:
需写在计算属性中
必须要用展开运算符(
...
)mapState参数接收一个配置对象,以键值形式,键为计算属性函数名称,值为State属性。
如果键值一样,则有另外一种数组写法形式:
computed:{ /*getSum(){ return this.$store.state.sum; }, getStudent(){ return this.$store.state.student; }, getSchool(){ return this.$store.state.school; }*/ ...mapState(['sum','student','school']), }
对于值来说,必须使用单引号包起来,不可以写出对象的简写形式,因为对象的简写形式是值为变量才可以,这里我的
sum、student、school
都是字符串。
7.2 mapGetters
mapGetters
:用于帮助我们映射getters
中的数据为计算属性
使用方法和mapState类似。
例如对于上面的案例来说:
computed:{
...mapGetters(['boostSum']), //数组形式,键值相同时可简写
...mapGetters({boostSum:'boostSum'}), //对象形式
//其他代码
},
效果仍然有
7.3 mapActions
mapActions
:用于帮助我们生成与actions
对话的方法,即:包含$store.dispatch(xxx)
的函数。
例如以前的写法:
这两个都是调用的dispatch,类比于mapState和mapGetters,这里可以简写为如下形式:
第一个key仍然是原本的方法名称,value则为Actions部分的方法名称。
注意,这里mapActions
和mapState
、mapGetters
还是有区别的。上图使用mapActions底层生成的代码类似于:
incrementOdd(value){
this.$store.dispatch('jiaOdd',value);
},
incrementWait(value){
this.$store.dispatch('jiaWait',value);
}
这里面有个参数value,如你在事件绑定的时候只写函数名,那么这里的value就是事件名称,如果你绑定事件的时候,写函数回调的时候给了值,那么这个value就是你传递的值。
如果不传值:
<button @click="incrementOdd">当前和为奇数在加</button>
<button @click="incrementWait">等500ms在加</button>
执行结果:
可见它将PointerEvent事件打印了出来,所以,你如果要用mapActions的话,有值就一定要传递。
7.4 mapMutations
mapMutations
:用于帮助我们生成与mutations
对话的方法,即:包含$store.commit(xxx)
的函数
使用方法和mapActions
类似:
注意:
mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
使用这四个map,必须要导入才可使用
import {mapState,mapGetters,mapActions,mapMutations} from "vuex";
8. Vuex模块化以及命名空间
之前我们的代码是这样写的:
将所有的dispatch需要的操作全部写在了actions对象中,所有的commit操作全部写在了mutations对象中,所有的数据写在了state对象中,所有的计算相关的写在了getters对象中。
现在有这么一种情况,就是由于一个项目往往是由多个程序员开发,所有的程序员全部来操作actions、mutations等,很容易就出现冲突,并且难以维护。所以就有了模块化和命名空间的需求:根据功能来划分模块,不同模块对象中有自己的actions、mutations、state、getters对象,这样各个模块只需要维护好自己的actions、mutations、state、getters对象即可。
使用示例:
修改store文件夹下的index.js文件:
import Vue from "vue"; import Vuex from 'vuex' //使用Vuex Vue.use(Vuex); const modulesOne = { namespaced:true, //如果要使用四个map中的任意一个,必须加上命名空间才可使用 actions:{ f1(){ console.log('我属于模块1'); } }, mutations:{}, state:{ test:'test1' }, getters:{ processData(state){ return state.test += '加工'; } } } const modulesTwo = { namespaced:true, //如果要使用四个map中的任意一个,必须加上命名空间才可使用 actions:{ f1(){ console.log('我属于模块2') } }, mutations:{}, state:{ test:'test2' }, getters:{ processData(state){ return state.test += '加工'; } } } //创建并暴露store export default new Vuex.Store({ modules:{ modulesOne, modulesTwo } });
根据不同功能划分模块,并且通过
modules
配置项配置到Store身上去。并且,在自己模块访问数据访问的是自己的,不会访问到其他模块的数据,所以里面的变量命名相同也没关系,只要不再一个模块中命名相同即可。开启命名空间后,组件中读取state数据:
我们先来看看使用这种模块化+命名空间之后,
Store
变为了什么:所以读取数据要使用如下方式:
//方式一:自己直接读取 this.$store.state.模块名称.state中的数据 //方式二:借助mapState读取: ...mapState('模块名称',['state中的数据']),
开启命名空间后,组件中读取getters数据:
我们再来看看使用模块+命名空间之后,getter中是什么形式:
可见他的不同之处在于它的键,他的键的组成为:模块名称/getter中的方法名称。
所以,读取getter的数据的方式为:
//方式一:自己直接读取 this.$store.getters['模块名称/getter中的方法名称'] //方式二:借助mapGetters读取: ...mapGetters('模块名称',['getter中的方法名称'])
开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch this.$store.dispatch('模块名称/getter中的方法名称',需要传递的数据) //方式二:借助mapActions: ...mapActions('模块名称',{计算属性的方法名:'要读取的state中的数据名称') //相比于之前的写法,也就在前面加了个模块名称,其他不变
例如map读取原来是:
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
现在map读取是:
...mapActions('模块名称',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
开启命名空间后,组件中调用commit
//方式一:自己直接commit this.$store.commit('模块名称/getter中的方法名称',需要传递的数据) //方式二:借助mapMutations: ...mapMutations('模块名称',{计算属性的方法名:'要读取的state中的数据名称'),
例如map读取原来是:
...mapMutations({increment:'JIA',decrement:'JIAN'}),
现在map读取是:
...mapMutations('模块名称',{increment:'JIA',decrement:'JIAN'}),