Vuex状态管理机制

Posted 勇敢*牛牛

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

建立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;

然后在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++
    

通过 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>

操作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:传入的参数*/
    

异步操作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","加油你是最棒的");
    

但是我们最终的目的是为了将异步得到的值,传给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);
        
    

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


modules模块化

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

export default
    state:
        num:100,
    ,
    getters:
        getNum(state)
            return state.num;
        
    ,
    mutations:,
    actions:

import count from '@/store/modules/count.js'
import data from '@/store/modules/data.js'
export default
   modules: 
        count,
        data
    


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

getters、mutations、actions不会有影响

vuex强制开始命名空间

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

namespaced:true,
export default
    namespaced:true,
    state:
        num:100,
    ,
    getters:
        getNum(state)
            return state.num;
        
    ,

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

 <h2>我从vuex的getters中读取数据——————$store.getters["count/getNum"] </h2>

this.$store.getters["count/getNum"]
this.$store.commit("count/addNum", 2)

这样就不会发生冲突。


辅助函数mapState、mapGetters、mapActions、mapMutations

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

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

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>

 有命名空间的写法

以上是关于Vuex状态管理机制的主要内容,如果未能解决你的问题,请参考以下文章

vue学习指南:第十五篇(详细) - Vuex

Vue:初次使用vueX

Vuex

详解Vuex常见问题

VueX状态管理

vuex 基础