• 【Vuex】状态管理机制


    vuex

    在这里插入图片描述

    什么是Vuex

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间的数据共享。如果您不打算开发大型单页应用,使用 Vuex 可能是繁琐冗余的。如果您的应用够简单,最好不要使用Vuex。

    使用Vuex管理数据优势

    • 能够在vuex中集中管理共享的数据,便于开发和后期进行维护

    • 能够高效的实现组件之间的数据共享,提高开发效率

    • 存储在vuex中的数据是响应式的,当数据发生改变时,页面中的视图也会同步更新

    • vuex中的数据操作可以在开发阶段通过开发调试工具来进行追踪,便于开发

    • 如果说组件中数量过多,且公用的数据和数据操作也多,就考虑使用统一的数据管理工具。例如登录后都会用到用户的此状态
      在这里插入图片描述


    vuex核心概念

    vuex对象中通过state来存储状态,除了state以外还有用来操作state中数据的方法集,以及当我们需要对state中的数据需要加工的方法集等等成员。
    成员列表:

    • state 存放状态(全局状态数据) 必填项

    • mutations 对于state成员进行同步修改操作(调试工具)

    • getters 获取state中的数据,类似于组件中的计算属性

    • actions 进行异步操作,异步得到结果后通知mutation修改state成员

    • modules 模块化状态管理,多状态文件管理时使用 开发项目时多为多模块项目

    • 在多模块vuex中会有配置 namespaced:true ->开启命名空间
      在这里插入图片描述
      首先,Vue组件如果调用某个VueX的方法过程中需要向后端请求时或者说出现异步操作时,需要dispatch VueX中actions的方法,以保证数据的同步。可以说,action的存在就是为了让mutations中的方法能在异步操作中起作用。

      如果没有异步操作,那么我们就可以直接在组件内提交状态中的Mutations中自己编写的方法来达成对state成员的操作。不建议在组件中直接对state中的成员进行操作,这是因为直接修改(例如:this.$store.state.name = ‘hello’)的话不能被VueDevtools所监控到。最后被修改后的state成员会被渲染到组件的原位置当中去。


    安装与配置

    方案1:在使用vue-cli命令创建项目时,勾选上vuex选项,即安装上vuex插件(推荐)
    方案2:通过后续的npm来进行安装

    npm i -S vuex@3
    
    • 1

    建立store/index.js文件

    import Vue from 'vue';
    import Vuex from 'vuex';
    
    Vue.use(Vuex);/* 以插件的方式注入到Vue类中 */
    
    const store = new Vuex.Store({/* 得到Vuex的Store对象 */
        /* 全局状态 必写选项*/
        state:{
            num:100
        }
    
    })
    
    export default store;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    然后在main.js中导入Vue配置项当中。
    然后在各个组件devtools的vuex中,就可以看见这个数据。

    this.$store.state.num
    可以利用计算属性来完成对于在vuex中获取state数据的简写
    
    
    组件中:
    <h2>我从vuex中读取数据——————{{$store.state.num}}</h2>
    <h2>我从vuex通过计算属性读取数据——————{{data}}</h2>
    操作这个数据:
    methods:{
        add(){
            this.$store.state.num++
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    通过 Vuex中的计算属性getters获取数据

    专门用于获取state状态中的数据,有缓存,只要依赖项不发生改变,那么他就读取缓存。

    const store = new Vuex.Store({/* 得到Vuex的Store对象 */
        /* 全局状态 必写选项*/
        state:{
            num:100
        },
        getters:{/* 专门获取state数据 */
            getNum(state){//这里的state就是状态数库
                return state.num>103?"超过103":state.num;
            }
        }
    })
    
    
    使用:
     <h2>我从vuex的getters中读取数据——————{{$store.getters.getNum}}</h2>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    操作Vuex中的数据

    同步操作mutations
    • state 中的数据,是可以直接写方法methods修改的,注意:是不推荐这种方式修

      • 直接修改,就会不安全 this.$store.state.num++
      • 每个组件实例,都可以通过 this.$store 来访问store对象里的共享数据
    • 修改操作state的数据,要通过mutations中配置的方法,在里面写方法【同步操作】

      • 所有的数据的操作,不要都在外面操作,放在vuex里面操作
      • 第二个也是为了同步操作使得这个devtools开发工具好去捕获数据操作。
      • 在组件中修改,就要通知这个mutations中的方法来操作,通过commit通知,也是同步方式;
    mutations:{
    	addNum(state,arg=1){//这里的state就是状态数库不变,arg调用时传入的参数,负荷
    		state.num += arg;
    		//setTimeout(()=>{
            //       state.num += arg;
            //},1000)
    	}
    }
    =============
    methods:{
        add(){
            this.$store.commit("addNum",2)/* c参数1:mutations中的那个方法,参数2:传入的参数*/
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    特别需要注意的是store的方法传入为多个参数的时候必须先利用对象的传参方法!!!!

    异步操作actions
    actions:{
        async addDate(store,arg){
            console.log(arg);
            let data = await get("/mock/data.json");
            /*public是静态资源根目录*/
            /*webpack 中的 devServer 中的express 把public设置为静态资源了*/
        }
    }
    =======
    通过dispath通知actions里执行那个异步方法;
    methods:{
        addasync(){
            this.$store.dispatch("addDate","加油你是最棒的");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    但是我们最终的目的是为了将异步得到的值,传给mutations做同步响应式处理,所以在通过commit通知mutations,执行相应的操作。
    伪代码处理:

        state:{
            data:{}
        },
        mutations:{
            addDATA(state,data){
                state.data = data;
            }
        },
        actions:{
            async addDate(store,arg){
                let data = await get("/mock/data.json");
                store.commit("addDATA",data);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    mock假数据,我写nodejs服务器;15-mock模拟数据备份


    modules模块化

    模块化,把state数据拆分到不同的模块中(不同文件中),把原来也在Vue.stroe实例配置中的代码,提取到不同的业务文件中。

    export default{
        state:{
            num:100,
        },
        getters:{
            getNum(state){
                return state.num;
            }
        },
        mutations:{},
        actions:{}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    import count from '@/store/modules/count.js'
    import data from '@/store/modules/data.js'
    
    • 1
    • 2
    export default{
       modules: {
            count,
            data
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    命名空间就是这样的做法,将这个空间名放在组件中进行调用。
    如果在组件中是:直接调用这个vux状态管理的数据的话,那就需要添加一个模块名或者空间名:
    $store.state.count.num
    this.$store.state.count.num
    但是对于

    getters、mutations、actions不会有影响
    
    • 1

    vuex强制开始命名空间

    因为但虽然在不同的模块中,但是状态管理最终是添加在一起的,所以有方法有同名的话仍然会执行这个同名函数:为了避免这种错误,vuex开启了命名空间。

    namespaced:true,
    
    • 1
    export default{
        namespaced:true,
        state:{
            num:100,
        },
        getters:{
            getNum(state){
                return state.num;
            }
        },
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样就对getters、mutations、actions三个起到空间作用。
    需要加上空间名才能调用:
    他在getNum之前加上了空间名:
    在这里插入图片描述

     <h2>我从vuex的getters中读取数据——————{{$store.getters["count/getNum"] }}</h2>
    
    this.$store.getters["count/getNum"]
    this.$store.commit("count/addNum", 2)
    
    • 1
    • 2
    • 3
    • 4

    这样就不会发生冲突。


    辅助函数mapState、mapGetters、mapActions、mapMutations

    使用场景:

    • mapState =》 computed
    • mapGetters =》computed
    • mapMutations =》methods
    • mapActions =》 methods

     在没有强制开启命名空间时的辅助函数写法

    mapState

    mapState返回的是一个对象,对象里面有一个方法。
    computed: {
    	...mapState({
    	   data:state=>state.count.num
    	})
    	//或者
    	...mapState(["count"])
    }
    数组中的元素,如果有模块化,则为modules中key的名称。
    ......mapState(["count"])
    返回值是一个:{ "num": 100 }对象
    如果要用它的话:
    
    <h2>我从vuex中读取数据——————{{ $store.state.count.num }}</h2>
    <h2>我从vuex通过计算属性读取数据——————{{ data }}</h2>
    <h2>我从vuex的getters中读取数据——————{{$store.getters["getNum"] }}</h2>
    <h2>我从vuex的mapState中读取数据——————{{count.num }}</h2>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    mapGetters

    这个方法在未强制开启命名空间时这样使用。
    
    ...mapGetters(["getNum"])
    返回一个vux里的getters里的方法:这个方法也就是参数指向的getter对象的方法名称。
    
    ...mapGetters({
        getnum:"getNum"
     })
    这种对象写法就可以将getters里的计算属性重新命名为key值,而这个value值就是:getters配置方法名称。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

     有命名空间的写法
    注:模块化后,开启了namespaced:true 配置后,注意方法的调用有2个参数

  • 相关阅读:
    网络练习题带答案
    柔性数组 +结构体中数组名与指针的区别
    不知道10年老电脑如何重装系统?其实很简单
    elementUi实现动态表格单元格合并span-method方法
    过午不食有依据吗
    基础 | JVM - [hashcode & 一致性 hash & ==]
    Hadoop3教程(三十):(生产调优篇)纠删码
    .NET性能优化-使用SourceGenerator-Logger记录日志
    代码随想录算法训练营第23期day3| 203.移除链表元素 ,707.设计链表,206.反转链表
    【github pages】: windows下构建一个github pages, 实时更新博客
  • 原文地址:https://blog.csdn.net/m0_46672781/article/details/126712297