Vue2中Vuex的基本使用
本文主要介绍vue2中vuex的基本用法,以及如何实现模块化
一.基本使用方法
因为这是在vue2中vuex的使用方法,所以注意安装vuex时要注意其版本,因为vue2不支持4.0及其以上的版本,我这里的版本为"vuex": "^3.6.2",也就是3.6.2版本。
下面我们创建两个简单的页面,一个页面包括加法与减法功能,另一个只有乘法功能。
<template>
<div>
<div>数值为:{{ sum }}</div>
<div>数值扩大10倍:{{ this.$store.getters.bigSum }}</div>
<el-button @click="add">+</el-button>
<el-button @click="reduce">-</el-button>
</div>
</template>
<script>
export default {
data() {
return {
}
},
computed:{
sum() {
return this.$store.state.num1
}
},
methods:{
add() {
this.$store.commit('ADD',1)
},
reduce() {
this.$store.commit("REDUCE",1)
}
}
}
</script>
<style>
</style>
<template>
<div>
<div>数值为:{{ multi }}</div>
<el-button @click="ride">x2</el-button>
</div>
</template>
<script>
export default {
data() {
return {
}
},
computed:{
multi() {
return this.$store.state.num2
}
},
methods:{
ride() {
this.$store.commit('RIDE',2)
}
}
}
</script>
<style>
</style>
其中src文件夹下的store文件下的index.js中的内容为:
getters一般用的比较少,它其实和计算属性一样,只不过它是自定义一个根据state中的某个值的变化而变化的属性。
在部分企业的要求中,mutations中的函数名往往全部采用字母大写的形式,当然小写的话也并不影响使用,如果你所在的公司都用小写,那你就不要用大写了,免得被人说闲话。
//src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
num1:0,
num2:1
},
mutations:{
ADD(state,value) {
state.num1 += value //等价于state.num1 = state.num1 + value
},
REDUCE(state,value) {
state.num1 -= value //等价于state.num1 = state.num1 - value
},
RIDE(state,value) {
state.num2 *= value
}
},
actions:{},
getters:{
bigSum(state) {
return state.num1*10
}
}
})
export default store
上面的案例中,我们没有用到vuex中的actions,一般actions中主要负责一些逻辑方面的处理,或者是有发送请求的需求,比如可以在actions中进行axios的发送。
现在我们提出一个新的要求,在加减功能的页面中,我们规定,如果增加的数是偶数,则页面提示“不支持增加偶数数值”。
首先我们在actions中写入部分代码:
通常情况下,尽量保持不要让mutations中的函数去处理过多逻辑,而是让其单纯的去做一个赋值操作。
这里我们在actions中定义了一个rejectEven方法,对其增加的数值进行判定,如果不为偶数则调用mutations中的ADD方法进行正常的增加操作。
其中的参数context是一个上下文对象,此对象中包含一个commit方法,可以利用其来操作mutatios中的函数。context中还有哪些东西,有兴趣的可自行打印console.log(context)进行查看。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
num1:0,
num2:1
},
mutations:{
ADD(state,value) {
state.num1 += value //等价于state.num1 = state.num1 + value
},
REDUCE(state,value) {
state.num1 -= value //等价于state.num1 = state.num1 - value
},
RIDE(state,value) {
state.num2 *= value
}
},
actions:{
rejectEven(context,value) {
if(value%2==0) {
alert('不支持增加偶数数值')
}else {
context.commit('ADD',value)
}
}
},
getters:{
bigSum(state) {
return state.num1*10
}
}
})
export default store
加减法功能页面中的代码也要进行调整
我们这里利用dispatch调用actions中的方法,并将增加的值改为2
<template>
<div>
<div>数值为:{{ sum }}</div>
<div>数值扩大10倍:{{ this.$store.getters.bigSum }}</div>
<el-button @click="add">+</el-button>
<el-button @click="reduce">-</el-button>
</div>
</template>
<script>
export default {
data() {
return {
}
},
computed:{
sum() {
return this.$store.state.num1
}
},
methods:{
add() {
this.$store.dispatch('rejectEven',2)
},
reduce() {
this.$store.commit("REDUCE",1)
}
}
}
</script>
<style>
</style>
因为是偶数,所以页面变成了这样
如果此时要求我们每次添加的值需要从服务器获取,则可以在actions发送axios,则代码调整为:
在这里我们引入了axios,并发送了一个请求,请求返回一个数值,我们拿到值后,便可进行逻辑判断。
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
num1:0,
num2:1
},
mutations:{
ADD(state,value) {
state.num1 += value //等价于state.num1 = state.num1 + value
},
REDUCE(state,value) {
state.num1 -= value //等价于state.num1 = state.num1 - value
},
RIDE(state,value) {
state.num2 *= value
}
},
actions:{
async rejectEven(context) {
let data = await axios.get('http://localhost:3000/productlist/testlist');
let value = data.data.data;
if(value%2==0) {
alert('不支持增加偶数数值')
}else {
context.commit('ADD',value)
}
}
},
getters:{
bigSum(state) {
return state.num1*10
}
}
})
export default store
以上就是vuex的一些基本用法。
二.引入辅助函数
组件中引入辅助函数的主要作用为,简化我们的写法,避免代码中出现过多的this.$store.xxxx,引入后,我们的代码变化为,以加减法功能这个页面为例:
新写法与原来写法最终实现的目的是一样的,这里需要注意的是采用辅助函数后,...mapMutations举例来说,我们无法像原来一样,在commit的时候同时传入参数,所以要在原来的方法中提前写入要传送的值。这里的@click=reduce(1)中,我们提前写好了数字1,也就是我们准备传送的参数
<template>
<div>
<div>数值为:{{ sum }}</div>
<div>数值扩大10倍:{{ bigSum }}</div>
<el-button @click="add">+</el-button>
<el-button @click="reduce(1)">-</el-button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
data() {
return {
}
},
computed:{
// sum() {
// return this.$store.state.num1
// }
// 对象写法
...mapState({sum:'num1'}),
...mapGetters({bigSum:'bigSum'})
},
methods:{
// add() {
// this.$store.dispatch('rejectEven')
// },
...mapActions({add:'rejectEven'}),
// reduce() {
// this.$store.commit("REDUCE",1)
// }
...mapMutations({reduce:'REDUCE'})
}
}
</script>
<style>
</style>
除了上面实例代码,注释部分所提到的对象写法外,我们还可以采用数组的写法,不过要使用数组写法,我们需要具备一定的条件,现在我们将加减法功能页面的代码做相应的调整,调整后的内容如下图所示:
<template>
<div>
<div>数值为:{{ num1 }}</div>
<div>数值扩大10倍:{{ bigSum }}</div>
<el-button @click="rejectEven">+</el-button>
<el-button @click="REDUCE(1)">-</el-button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
data() {
return {
}
},
computed:{
// 数组写法
...mapState(['num1']),
...mapGetters(['bigSum'])
},
methods:{
// 数组写法
...mapActions(['rejectEven']),
...mapMutations(['REDUCE'])
}
}
</script>
<style>
</style>
相信聪明的小伙伴已经看出来了,我们将原来的计算属性的属性名,以及自己起的方法的名字完全与store文件夹下的,index.js文件中的state中的变量名,以及各个相对应的方法名(mutations,actions中的方法名)都统一了,也就是名字一模一样了,也是在这种情况下,我们才能采用数组这种写法。
三.模块化
我们写的乘法功能页面,在这一刻终于要被提及了,在这之前,请先观察下我们store文件夹下的index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex);
const store = new Vuex.Store({
state:{
num1:0,
num2:1
},
mutations:{
ADD(state,value) {
state.num1 += value //等价于state.num1 = state.num1 + value
},
REDUCE(state,value) {
state.num1 -= value //等价于state.num1 = state.num1 - value
},
RIDE(state,value) {
state.num2 *= value
}
},
actions:{
async rejectEven(context) {
let data = await axios.get('http://localhost:3000/productlist/testlist');
let value = data.data.data;
if(value%2==0) {
alert('不支持增加偶数数值')
}else {
context.commit('ADD',value)
}
}
},
getters:{
bigSum(state) {
return state.num1*10
}
}
})
export default store
你会发现在state中有两个变量,num1,num2;mutations中有两个方法,但其中一个方法是服务于乘法功能页面的,其余两个则服务于加减功能页面,而getters中的bigSum也是只服务于加减功能页面,假如后续我们的页面继续增多,每个页面都需要有自己的变量存储在state中,那这个index.js文件中乱七八糟的东西就会越来越多,我们希望的是这个state中的所有变量都只服务于一个页面,mutations中的方法也都服务于一个页面,所以我们引入了模块的概念,这里我们对代码稍作调整:
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex);
// 加减法
const add = {
namespaced:true, //采用模块化后,默认为false,要设置为true,不然后续无法访问到此对象中的属性
state:{
num1:0
},
mutations:{
ADD(state,value) {
state.num1 += value //等价于state.num1 = state.num1 + value
},
REDUCE(state,value) {
state.num1 -= value //等价于state.num1 = state.num1 - value
}
},
actions:{
async rejectEven(context) {
let data = await axios.get('http://localhost:3000/productlist/testlist');
let value = data.data.data;
if(value%2==0) {
alert('不支持增加偶数数值')
}else {
context.commit('ADD',value)
}
}
},
getters:{
bigSum(state) {
return state.num1*10
}
}
}
// 乘法
const multi = {
namespaced:true,
state:{
num2:1
},
mutations:{
RIDE(state,value) {
state.num2 *= value
}
},
actions:{},
getters:{}
}
const store = new Vuex.Store({
modules:{
add, //同add:add,前面add为自己起的模块名,后面的add为上方定义的const add,这里采用了简写
multi
}
})
export default store
同样的,加减功能页面也要做相应的调整:
其实就是在原来写法的基础上,在最前面添加了模块的名字,比如说这里的名字为add
<template>
<div>
<div>数值为:{{ num1 }}</div>
<div>数值扩大10倍:{{ bigSum }}</div>
<el-button @click="rejectEven">+</el-button>
<el-button @click="REDUCE(1)">-</el-button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
data() {
return {
}
},
computed:{
// 其实就是在原来写法的基础上,在最前方添加了模块的名字,比如说这里的名字为add
// 数组写法
...mapState('add',['num1']),
...mapGetters('add',['bigSum'])
// 对象写法
// ...mapState('add',{num1:'num1'}),
// ...mapGetters('add',{bigSum:'bigSum'})
},
methods:{
// 数组写法
...mapActions('add',['rejectEven']),
...mapMutations('add',['REDUCE'])
// 对象写法
// ...mapActions('add',{rejectEven:'rejectEven'}),
// ...mapMutations('add',{REDUCE:'REDUCE'})
}
}
</script>
<style>
</style>
假如不使用辅助函数,采用最原始的写法则为下图所示:
<template>
<div>
<div>数值为:{{ num1 }}</div>
<div>数值扩大10倍:{{ bigSum }}</div>
<el-button @click="rejectEven">+</el-button>
<el-button @click="REDUCE">-</el-button>
</div>
</template>
<script>
// import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
data() {
return {
}
},
computed:{
// 其实就是在原来写法的基础上,在最前方添加了模块的名字,比如说这里的名字为add
// 数组写法
// ...mapState('add',['num1']),
// ...mapGetters('add',['bigSum'])
// 对象写法
// ...mapState('add',{num1:'num1'}),
// ...mapGetters('add',{bigSum:'bigSum'})
num1() {
return this.$store.state.add.num1
},
bigSum() {
return this.$store.getters['add/bigSum']
}
},
methods:{
// 数组写法
// ...mapActions('add',['rejectEven']),
// ...mapMutations('add',['REDUCE'])
// 对象写法
// ...mapActions('add',{rejectEven:'rejectEven'}),
// ...mapMutations('add',{REDUCE:'REDUCE'})
rejectEven() {
this.$store.dispatch('add/rejectEven')
},
REDUCE() {
this.$store.commit('add/REDUCE',1)
}
}
}
</script>
<style>
</style>
对此感到难以记忆的小伙伴可以在mounted中输出this.$store进行观察,则可看出端倪,像dispatch,commit等等都是其上面的方法。
最后我们可以将store文件夹下定义的const add 与const multi提取出来,在store文件夹下再创建两个js文件,并将其导入到index.js文件中,这样便实现了vuex模块化的管理。
更多推荐
所有评论(0)