Vuex

头像
後來
    阅读 8 分钟
    1

    Vuex是什么

    概念:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。适用于任意组件之间通信。

    PS:集中式(可以理解为学生都在课堂,老师给他们上课),还有分布式(可以理解为老师会72变,变成N个人,去学生家里给每个学生上课)

    什么时候使用Vuex

    如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。

    那么当我们开大大型单页面组件的时候,一定要用Vuex吗?

    • 当多个组件依赖于同意状态
    • 当来自不同组件的行为需要改变同一状态

    Vuex图解

    来自于官方
     title=

    Vuex的store中都有啥

    • state:存储公共数据的
    • mutations:操作公共数据的
    • actions:触发mutations的(这一步在某些时候不需要,可以直接调用mutations里面的方法)
    • getters:基于state中的数据再做处理的(可以理解为store的计算属性)

    Vuex中的map系列

    // 这两个是当我们这个页面使用不止一个store中的数据的时候,可以使用
    import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
    
    methods: {
        increase() {
            // this.$store.dispatch('increase',this.val)
            // 如果没有复杂的逻辑,例如调用接口,我们可以直接接调用commit,不需要dispatch
            this.$store.commit('INCREASE',this.val)
        },
        // 这样就可以直接使用了,不用像上面样的自己写方法调用,这样是直接调用的commit,不经过actions,同样有数组的写法,名称保持统一
        ...mapMutations({increase1:'INCREASE'}),
        // 这样就可以直接使用了,不用像上面样的自己写方法调用,调用actions,同样有数组的写法,名称保持统一
        ...mapActions({increase2:'increase'})
    },
    computed:{
        // 这是对象写法
        // ...mapState({sum:'sum',userId:'userId',userName:'userName'}),
        // ...mapGetters({bigSum:'bigSum'})
        // 这是数组写法,这种写法,名字和store必须要一样
        ...mapState(['sum','userId','userName']),
        ...mapGetters(['bigSum'])
    }

    demo

    // store/index.js
    
    // 引入Vuex
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    // 创建state--用于存储数据
    const state = {
        sum: 0,
        userId: 12345678,
        userName: '景天'
    }
    
    // 创建mutations--用于操作数据(state)
    const mutations = {
        INCREASE(state,value) {
            state.sum += value
        },
        DECREASE(state,value) {
            state.sum -= value
        }
    }
    
    // 创建actions--用于响应组件中的动作
    // 如果调用的是store.dispatch来修改store里面的值,会触发这个,再触发mutations里面的方法
    const actions = {
        // 接收两个参数
        // 第一个参数可以理解为是一个小型的store,可以获取和使用store身上的东西,第二个参数是你传进来的值
        increase(context,value) {
            // INCREASE这个大写不大写无所谓,只是有些人喜欢区分
            context.commit('INCREASE',value)
        },
        decrease(context,value) {
            // INCREASE这个大写不大写无所谓,只是有些人喜欢区分
            context.commit('DECREASE',value)
        }
    }
    
    // 基于state中的数据做处理
    const getters = {
        bigSum(state) {
            return state.sum * 10
        }
    }
    
    // 导出使用
    export default new Vuex.Store({
        state,
        actions,
        mutations,
        getters
    })

    两个组件演示Vuex

    // 组件1
    <template>
        <div class="increase">
            <div>当前的和为:{{sum}}</div>
            <div>显示10倍值:{{bigSum}}</div>
            <select v-model.number="val">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
            </select>
            <button @click="increase">+</button>
            <!-- 下面这一行传值进去是给mapMutations使用的,不然mapMutations获取不到你的值 -->
            <button @click="increase1(val)">mapMutations的+</button>
            <!-- 下面这一行传值进去是给mapActions使用的,不然mapActions获取不到你的值 -->
            <button @click="increase2(val)">mapActions的+</button>
        </div>
    </template>
    
    <script>
    // 这几个是当我们这个页面使用不止一个store中的数据的时候,可以使用
    import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
    export default {
        data() {
            return {
                val: 1
            }
        },
        methods: {
            increase() {
                // this.$store.dispatch('increase',this.val)
                // 如果没有复杂的逻辑,例如调用接口,我们可以直接接调用commit,不需要dispatch
                this.$store.commit('INCREASE',this.val)
            },
            // 这样就可以直接使用了,不用像上面样的自己写方法调用,这样是直接调用的commit,不经过actions,同样有数组的写法,名称保持统一
            ...mapMutations({increase1:'INCREASE'}),
            // 这样就可以直接使用了,不用像上面样的自己写方法调用,调用actions,同样有数组的写法,名称保持统一
            ...mapActions({increase2:'increase'})
        },
        // computed中的这些其实可以不用,只是你写的时候要写很多,这里相当于是优化代码
        computed:{
            // 设定一个值接收store中的值,这样就不用写一大串了
            // 这是对象写法
            // ...mapState({sum:'sum',userId:'userId',userName:'userName'}),
            // ...mapGetters({bigSum:'bigSum'})
            // 这是数组写法,这种写法,名字和store必须要一样
            ...mapState(['sum','userId','userName']),
            ...mapGetters(['bigSum'])
        }
    };
    </script>
    
    <style>
    .increase {
        background-color: #ccc;
    }
    </style>
    // 组件2
    <template>
        <div class="decrease">
            <div>当前的和为:{{$store.state.sum}}</div>
            <div>显示10倍值:{{$store.getters.bigSum}}</div>
            <select v-model.number="val">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
            </select>
            <button @click="decrease">-</button>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                val: 1
            }
        },
        methods: {
            decrease() {
                // this.$store.dispatch('decrease',this.val)
                this.$store.commit('DECREASE',this.val)
            }
        }
    };
    </script>
    
    <style>
    .decrease {
        background-color: #eee;
    }
    </style>

    复杂demo

    实际业务中,可能会有很多模块,那么同样会有很多的state,mutations,所以,就有了分块的写法

    // store/index.js
    
    // 引入Vuex
    import Vue from 'vue'
    import Vuex from 'vuex'
    import user from './modules/user'
    import module1 from './modules/module1' // 这个里面的配置和user一样,只是业务逻辑的区别
    Vue.use(Vuex)
    
    // 导出使用
    export default new Vuex.Store({
        modules: {
            user: user,
            module1: module1
        }
    })
    // ./modules/user
    
    export default {
        namespaced: true,   // 不写不能直接使用名称
        state: {
            sum: 0,
            userId: 12345678,
            userName: '景天'
        },
        mutations: {
            INCREASE(state,value) {
                state.sum += value
            },
            DECREASE(state,value) {
                state.sum -= value
            }
        },
        actions: {
            increase(context,value) {
                context.commit('INCREASE',value)
            },
            decrease(context,value) {
                context.commit('DECREASE',value)
            }
        },
        getters: {
            bigSum(state) {
                return state.sum * 10
            }
        }
      }

    同样两个组件演示

    // 组件1
    
    <template>
        <div class="increase">
            <div>当前的和为:{{sum}}</div>
            <div>显示10倍值:{{bigSum}}</div>
            <select v-model.number="val">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
            </select>
            <button @click="increase">+</button>
            <!-- 下面这一行传值进去是给mapMutations使用的,不然mapMutations获取不到你的值 -->
            <button @click="increase1(val)">mapMutations的+</button>
            <!-- 下面这一行传值进去是给mapActions使用的,不然mapActions获取不到你的值 -->
            <button @click="increase2(val)">mapActions的+</button>
        </div>
    </template>
    
    <script>
    // 这几个是当我们这个页面使用不止一个store中的数据的时候,可以使用
    import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
    export default {
        data() {
            return {
                val: 1
            }
        },
        methods: {
            increase() {
                // this.$store.dispatch('user/increase',this.val)
                this.$store.commit('user/INCREASE',this.val)
            },
            ...mapMutations('user',{increase1:'INCREASE'}),
            ...mapActions('user',{increase2:'increase'})
        },
        computed:{
            ...mapState('user',{sum:'sum',userId:'userId',userName:'userName'}),
            ...mapGetters('user',{bigSum:'bigSum'})
            // ...mapState('user',['sum','userId','userName']),
            // ...mapGetters('user',['bigSum'])
        }
    };
    </script>
    
    <style>
    .increase {
        background-color: #ccc;
    }
    </style>
    // 组件2
    
    <template>
        <div class="decrease">
            <div>当前的和为:{{$store.state.user.sum}}</div>
            <!-- modules模式下的getters,需要这么获取值 -->
            <div>显示10倍值:{{$store.getters['user/bigSum']}}</div>
            <select v-model.number="val">
                <option value="1">1</option>
                <option value="2">2</option>
                <option value="3">3</option>
            </select>
            <button @click="decrease">-</button>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                val: 1
            }
        },
        methods: {
            decrease() {
                // this.$store.dispatch('user/decrease',this.val)
                this.$store.commit('user/DECREASE',this.val)
            }
        }
    };
    </script>
    
    <style>
    .decrease {
        background-color: #eee;
    }
    </style>

    後來
    1 声望0 粉丝

    « 上一篇
    Vue-EventBus
    下一篇 »
    Vue-nextTick