一.基本使用方法

因为这是在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模块化的管理。

Logo

前往低代码交流专区

更多推荐