• Vue学习(二十)vuex


    vuex

    概念

    专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对Vue应用中多个组件的共享状态进行集中式管理(读/写),也是一种组件间通信方式,并且适用于任意组件简单通信。

    使用场景

    1. 多个组件依赖同一状态。
    2. 来自不同组件的行为需要变更同一状态。

    vuex工作原理

    在这里插入图片描述

    下载Vuex

    # 默认的下载是最高版本的
    npm i vuex
    	# 或
    yarn add vuex
    # 下载3版本的vuex
    npm i vuex@3
    	# 或
    yarn add vuex@3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    搭建Vuex环境

    1. 创建文件src/store/index.js
    // 该文件用于创建Veux中最为核心的store
    
    import Vue from 'vue'
    
    // 引入Vuex
    import Vuex from 'vuex'
    // 使用vuex插件
    Vue.use(Vuex);
    
    // 准备actions  用于响应组件中的动作
    const actions = {}
    // 准备mutations    用于加工数据
    const mutations = {}
    // 准备state    用于存储数据
    const state = {}
    // 创建store
    /* const store = new Vuex.Store({
        actions,
        mutations,
        state,
    })
    // 导出store
    export default store */
    // 创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    1. main.js中创建vm时引入store配置项
    // 引入Vue
    import Vue from "vue";
    // 引入App组件
    import App from "./App"
    // 引入store
    import store from './store'
    
    // 关闭生产提示
    Vue.config.productionTip = false
    // 创建vm
    new Vue({
        render: h => h(App),
        store,
        // store: store
        beforeCreate() {
            // 安装全局事件总线
            Vue.prototype.$bus = this
        },
    }).$mount("#app");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    Vuex基础小案例

    1. 组件读取Vuex中的数据:[this.]$store.state.内容
    2. 组件修改Vuex中的数据:[this.]$store.despath("actions方法名", 数据)[this.]$store.commit("mitations方法名", 数据)
      src/store/index.js
    // 该文件用于创建Veux中最为核心的store
    
    import Vue from 'vue'
    
    // 引入Vuex
    import Vuex from 'vuex'
    // 使用vuex插件
    Vue.use(Vuex);
    
    // 准备actions  用于响应组件中的动作
    const actions = {
        /* incremnet(context, value) {
            // console.log("actions中的incremnet被调用了", context, value);
            context.commit("INCREMNET", value)
        },
        decremnet(context, value) {
            // console.log("actions中的decremnet被调用了", context, value);
            context.commit("DECREMNET", value)
        }, */
        incremnetOdd(context, value) {
            // console.log("actions中的incremnetOdd被调用了", context, value);
            if (context.state.sum % 2) {
                context.commit("INCREMNET", value)
            }
        },
        incremnetWait(context, value) {
            // console.log("actions中的incremnetWait被调用了", context, value);
            setTimeout(() => {
                context.commit("INCREMNET", value)
            }, 500)
        },
    }
    // 准备mutations    用于加工数据
    const mutations = {
        INCREMNET(state, value) {
            // console.log("mutations中的INCREMNET被调用了", context, value);
            state.sum += value
        },
        DECREMNET(state, value) {
            // console.log("mutations中的DECREMNET被调用了", context, value);
            state.sum -= value
        }
    }
    // 准备state    用于存储数据
    const state = {
        sum: 0,  // 当前的求和
    }
    // 创建store
    /* const store = new Vuex.Store({
        actions,
        mutations,
        state,
    })
    
    
    // 导出store
    export default store */
    // 创建并暴露store
    export default new Vuex.Store({
        actions,
        mutations,
        state
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    Count.vue

    <template>
      <div>
        <h1>当前求和为:{{$store.state.sum}}</h1>
        <select v-model.number="num">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <!-- <option :value="1">1</option>
            <option :value="2">2</option>
            <option :value="3">3</option> -->
        </select>
        <button @click="incremnet">+</button>
        <button @click="decremnet">-</button>
        <button @click="incremnetOdd">当前求和为奇数再加</button>
        <button @click="incremnetWait">等一等再加</button>
      </div>
    </template>
    
    <script>
        export default {
            name: 'Count',
            data() {
                return {
                    num: 1, // 当前选择的数据
                    
                }
            },
            methods: {
                incremnet() {
                    this.$store.commit('INCREMNET', this.num);
                },
                decremnet() {
                    this.$store.commit('DECREMNET', this.num);
                },
                incremnetOdd() {
                    /* if (this.$store.state.sum % 2) {
                        this.$store.dispatch('incremnet', this.num);
                    } */
                    this.$store.dispatch('incremnetOdd', this.num);
                },
                incremnetWait() {
                    /* setTimeout(() => {
                        this.$store.dispatch('incremnet', this.num);
                    }, 500) */
                    this.$store.dispatch('incremnetWait', this.num);
                }
            },
            mounted() {
                
            },
        }
    </script>
    
    <style scoped>
        button {
            margin-left: 5px;
        }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    getters使用

    1. 概念: 当state中的数据需要经过加工后再使用,且多个组件进行复用,可以使用getters进行加工。
    2. 配置:store/index.js中追加配置项getters(getter写返回值)
    ...
    const getters = {
        bigSum(state) {
            return state.sum * 10
        }
    }
    ...
    export default new Vuex.Store({
        actions,
        mutations,
        state,
        getters
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 使用: 组件中读取数据[this.]$store.getters.内容

    四个map方法使用

    mapState方法

    映射state中的数据计算属性

    import {mapState} from 'vuex'
    ...
    computed: {
       /* sum() {
           return this.$store.state.sum
       },
       school() {
           return this.$store.state.school
       },
       subject() {
           return this.$store.state.subject
       }, */
       // 借助mapState生成计算属性,获取state中的数据。对象写法
       // ...mapState({sum: "sum", school: "school", subject: "subject"}),
       // 借助mapState生成计算属性,获取state中的数据。数组写法
       ...mapState(["sum", "school", "subject"]),
       bigSum() {
           return this.$store.getters.bigSum
       },
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    mapGetters方法

    映射getters中的数据计算属性

    import {mapGetters} from 'vuex'
    ...
    computed: {
    	/* bigSum() {
    	    return this.$store.getters.bigSum
    	}, */
    	// 借助mapGetters生成计算属性,获取getters中的数据。对象写法
    	// ...mapGetters({bigSum: "bigSum"}),
    	// 借助mapGetters生成计算属性,获取getters中的数据。数组写法
    	...mapGetters(["bigSum"]),
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    mapActions方法

    生成actions方法,即包含```$store.dispatch(xxx)的函数

    ...
    <button @click="incremnetOdd(num)">当前求和为奇数再加</button>
    <button @click="incremnetWait(num)">等一等再加</button>
    ...
    import {mapActions} from 'vuex'
    ... 
    methods: {
        /* incremnetOdd() {
            // if (this.$store.state.sum % 2) {
            //     this.$store.dispatch('incremnet', this.num);
            // }
            this.$store.dispatch('incremnetOdd', this.num);
        },
        incremnetWait() {
            // setTimeout(() => {
            //     this.$store.dispatch('incremnet', this.num);
            // }, 500)
            this.$store.dispatch('incremnetWait', this.num);
        }, */
        // 对象写法
        // ...mapActions({incremnetOdd: "incremnetOdd", incremnetWait: "incremnetWait"}),
        // 数组写法
        ...mapActions(["incremnetOdd", "incremnetWait"]),
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    mapMutations方法

    生成mapMutations方法,即包含```$store.commit(xxx)的函数

    1. 对象写法
    <button @click="incremnet(num)">+</button>
    <button @click="decremnet(num)">-</button>
    ...
    import {mapMutations} from 'vuex'
    ... 
    methods: {
      /* incremnet() {
          this.$store.commit('INCREMNET', this.num);
      },
      decremnet() {
          this.$store.commit('DECREMNET', this.num);
      }, */
      // 对象写法
      ...mapMutations({incremnet: 'INCREMNET', decremnet: 'DECREMNET'}),
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 数组写法
    <button @click="INCREMNET(num)">+</button>
    <button @click="DECREMNET(num)">-</button>
    ...
    import {mapMutations} from 'vuex'
    ... 
    methods: {
      /* incremnet() {
          this.$store.commit('INCREMNET', this.num);
      },
      decremnet() {
          this.$store.commit('DECREMNET', this.num);
      }, */
      // 数组写法
      ...mapMutations(['INCREMNET', 'DECREMNET']),
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Count.vue

    <template>
      <div>
        <h1>当前求和为:{{sum}}</h1>
        <h3>当前求和放大10倍为:{{bigSum}}</h3>
        <h3>我在{{school}},学习{{subject}}</h3>
        <select v-model.number="num">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
            <!-- <option :value="1">1</option>
            <option :value="2">2</option>
            <option :value="3">3</option> -->
        </select>
        <button @click="incremnet(num)">+</button>
        <button @click="decremnet(num)">-</button>
        <button @click="incremnetOdd(num)">当前求和为奇数再加</button>
        <button @click="incremnetWait(num)">等一等再加</button>
      </div>
    </template>
    
    <script>
        import {mapState, mapGetters, mapMutations, mapActions} from 'vuex'
        export default {
            name: 'Count',
            data() {
                return {
                    num: 1, // 当前选择的数据
                }
            },
            computed: {
                // 借助mapState生成计算属性,获取state中的数据。对象写法
                // ...mapState({sum: "sum", school: "school", subject: "subject"}),
                // 借助mapState生成计算属性,获取state中的数据。数组写法
                ...mapState(["sum", "school", "subject"]),
    
                // 借助mapGetters生成计算属性,获取getters中的数据。对象写法
                // ...mapGetters({bigSum: "bigSum"}),
                // 借助mapGetters生成计算属性,获取getters中的数据。数组写法
                ...mapGetters(["bigSum"]),
            },
            methods: {
                /* incremnet() {
                    this.$store.commit('INCREMNET', this.num);
                },
                decremnet() {
                    this.$store.commit('DECREMNET', this.num);
                }, */
                // 对象写法
                ...mapMutations({incremnet: 'INCREMNET', decremnet: 'DECREMNET'}),
                // 数组写法
                // ...mapMutations(['INCREMNET', 'DECREMNET']),
    
                /* incremnetOdd() {
                    // if (this.$store.state.sum % 2) {
                    //     this.$store.dispatch('incremnet', this.num);
                    // }
                    this.$store.dispatch('incremnetOdd', this.num);
                },
                incremnetWait() {
                    // setTimeout(() => {
                    //     this.$store.dispatch('incremnet', this.num);
                    // }, 500)
                    this.$store.dispatch('incremnetWait', this.num);
                }, */
                // 对象写法
                // ...mapActions({incremnetOdd: "incremnetOdd", incremnetWait: "incremnetWait"}),
                // 数组写法
                ...mapActions(["incremnetOdd", "incremnetWait"]),
            },
            mounted() {
                
            },
        }
    </script>
    
    <style scoped>
        button {
            margin-left: 5px;
        }
    </style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80

    模块化与命名空间

    1. 目的:让代码更好维护,让多种数据分类更加明确
    2. 修改stroe.js
    ...
    const countOption = {
        namespaced: true,
        actions: {
            incremnetOdd(context, value) {
                // console.log("actions中的incremnetOdd被调用了", context, value);
                if (context.state.sum % 2) {
                    context.commit("INCREMNET", value)
                }
            },
            incremnetWait(context, value) {
                // console.log("actions中的incremnetWait被调用了", context, value);
                setTimeout(() => {
                    context.commit("INCREMNET", value)
                }, 500)
            },
        },
        mutations: {
            INCREMNET(state, value) {
                // console.log("mutations中的INCREMNET被调用了", context, value);
                state.sum += value
            },
            DECREMNET(state, value) {
                // console.log("mutations中的DECREMNET被调用了", context, value);
                state.sum -= value
            },
        },
        state: {
            sum: 0,  // 当前的求和
            school: "尚硅谷",
            subject: "前端",
        },
        getters: {
            bigSum(state) {
                return state.sum * 10
            }
        },
    }
    const personOption = {
        namespaced: true,
        actions: {
            addPersonWang(context, value) {
                if (value.name.indexOf("王") === 0) {
                    context.commit("ADD_PERSON", value);
                } else {
                    alert("添加的人必须姓王")
                }
                
            }
        },
        mutations: {
            ADD_PERSON(state, value) {
                state.personList.unshift(value)
            }
        },
        state: {
            personList: [
                {id: "001", name: "张三"}
            ]
        },
        getters: {
            firstPersonName(state) {
                return state.personList[0].name
            }
        },
    }
    ...
    // 创建并暴露store
    export default new Vuex.Store({
        modules: {
            countAbout: countOption,
            personAbout: personOption,
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    1. 开启命名空间后,组件中读取state数据
    // 方式一:自己读取
    this.$store.state.modules中的命名.数据
    // 借助mapState
    ...mapState('modules中的命名', ["数据名"]),
        // 或
    ...mapState('modules中的命名', {"自定义对象名": "state中对象名"}),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 开启命名空间后,组件中读取getters数据
    // 方式一:自己读取
    this.$store.getters['modules中的命名/数据名']
    // 借助mapGetters
    ...mapGetters('modules中的命名', ["数据"]),
        // 或
    ...mapGetters('modules中的命名', {"自定义对象名": "getters中数据名"}),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 开启命名空间后,组件中调用dispatch
    // 方式一:自己读取
    this.$store.dispatch['modules中的命名/dispatch函数名']
    // 借助mapDispatch
    ...mapDispatch('modules中的命名', ["dispatch函数名"]),
        // 或
    ...mapDispatch('modules中的命名', {"自定义名": "dispatch函数名"}),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 开启命名空间后,组件中调用commit
    // 方式一:自己读取
    this.$store.dispatch['modules中的命名/commit函数名']
    // 借助mapCommit
    ...mapCommit('modules中的命名', ["commit函数名"]),
        // 或
    ...mapCommit('modules中的命名', {"自定义名": "commit函数名"}),
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    odoo 给列表视图添加按钮实现数据文件导入
    Python时间模块(datetime)
    JDBC笔记
    Git 分支管理
    数据结构 | 图
    Bootstrap的small标签
    最简单明了的整数拆分解析
    C语言:数组指针
    《吐血整理》高级系列教程-吃透Fiddler抓包教程(29)-Fiddler如何抓取Android7.0以上的Https包-终篇
    dockerfile创建镜像与容器卷
  • 原文地址:https://blog.csdn.net/qq_29107721/article/details/125491910