• 前端框架Vue自学之Vuex(八)


    我的最新博客在:Secret_wu's coding note

    终极目标:掌握和使用Vue(全家桶:Core+Vue-router+Vuex)

    本博客目的:记录Vue学习的进度和心得(Vuex,终于到Vuex了,泪目)

    内容:学习和使用Vuex。

    正文:

    Vuex

    一、Vuex概念和作用解析

      1、认识Vuex

      Vuex是一个专为vue.js应用程序开发的状态管理模式

      它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex也集成到Vue的官方调试工具,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。Vuex也是响应式的。

      2、状态管理

      我们可以简单地将状态管理看成把需要多个组件共享的变量(状态)全部存储在一个对象里,然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。

       看上去我们可以直接修改Vue的原型实现共享变量(自己封装也很麻烦),但其不是响应式的。而Vuex就是为了提供一个在多个组件间共享状态的插件并且还是响应式的。

      3、管理什么状态

      有什么状态是需要我们在多个组件间共享的呢?

      如果我们做过大型开发,一定遇到过多个状态,在多个界面间的共享问题。比如用户的登录状态、用户名称、头像、地理位置信息等等。比如商品的收藏、购物车的物品等等。这些状态信息,我们都可以放在统一的地方,对它进行保存和管理(用Vuex),而且它们还是响应式的。

    二、单界面到多界面状态管理切换

      1、单界面的状态管理

      

       state储存当前界面(组件)的状态(姑且看成在vue实例中的data中的属性),这个状态是在view(视图层)中显示,当发生一些行为actions时,会修改状态,这个状态也是通过view显示。使用Vue就可以做到单界面的状态管理。

      2、多界面状态管理

      当我们不想只在一个界面进行状态管理,即想多界面状态管理。也就是说对于某些状态(状态1,2,3)来说只属于我们某一个视图,但是也有一些状态(a,b,c)属于多个视图共同想要维护的。通常,状态1,2,3放在自己的房间里,自己管理自己;但是状态a,b,c,我们希望交给一个大管家来统一帮助我们管理,而Vuex就是为我们提供这个大管家的工具。

      全局单例模式(大管家)。我们现在要做的就是将共享的状态抽取出来,交给我们的大管家,统一进行管理。之后,我们每个视图,按照我们规定好的规定,进行访问和修改等操作。这就是Vuex背后的基本思想。(单例模式:保证一个类仅有一个实例,并提供一个访问它的全局访问点。)

      首先,安装。Vuex是个插件,先安装,npm install vuex --save(运行时依赖)。

      接着,创建Vuex的文件夹(src下)。通常我们会把使用Vuex的代码放置在一个文件夹内进行管理(类似使用vue-router我们会创建一个router文件夹),所以我们创建一个名为store的文件夹(通常起store仓库,而不是vuex)。

      然后在store文件夹下,创建index.js。导入Vue和Vuex,安装插件(Vue.use(插件)),创建Vuex.store对象(放置state,mutation,actions,getters,modules),接着导出store。然后在main.js中使用,挂载。

      

        

       Vuex.store对象中,state就是放置共享的状态(可以简单先看成变量)。由于store已经挂载在vue实例上,也就是所有的组件都可以使用和这个状态,通过$store来调用这个index.js中的store,即Vuex.store实例对象。然后通过$store.state.X属性来获取state中的X属性。

       官方的图。可以发现组件不是直接地获取和修改state对象的,是有一定流程的。devtools是Vue开发的一个浏览器插件,可以帮我们记录跟踪每次修改state的记录。注意,组件可以直接操作到mutations,但一定是得是同步操作(因为devtools也是同步的),而如果是异步操作,就必须经过actions的流程。而异步操作通常是网络请求,所以actions和后端backend API是可以结合使用的。

      3、devtools和mutations

      devtools是vue开发的一个浏览器插件。假设我们使用Chrome浏览器,打开Chrome网上应用,搜索devtools。

       点击添加,当我们重新打开Chrome浏览器,打开控制台,选项多个vue,说明安装成功。

      

       这个devtools插件就是用来调试vue程序的(包括Vuex)。点击第二个按钮,就是专门调试Vuex的界面,例如我之前在index.js代码中添加了state的一个属性count,浏览器也显示出来了。此外,如果我们是通过mutations修改的状态,也是可以在这里面进行跟踪。这也是官网推荐我们不要在组件中直接修改state的原因之一。

      

       mutations中,通常定义一些方法,而这些方法的默认参数就是state对象,所以操作state对象的一些属性非常容易。

      (mutations里面定义方法)

       然后假如在App.vue调用这个方法,(首先监听事件等),然后在methods中定义方法,使用这个mutation的方法,但注意得使用.commit('方法名'),而不是直接.方法名。

      

       然后用devtools查看,发现的确可以追踪状态的改变。并且选择某次的修改(从右边的记录栏里),可以查看当时的state情况。

    三、Vuex核心

      Vuex核心概念:State,Getters,Mutation,Action,Module。State保存状态相关的信息,Getters优点类似组件的计算属性,Mutation通常定义一些操作状态的方法,Action主要做些异步操作,Module用于划分模块,针对不同模型,进行一些保存等操作。

      1、state单一状态树的理解

      state单一状态树(Single Source of Truth,单一数据源)

      例如,在我们国内有很多信息需要被记录,例如上学时的个人档案,工作后的社保记录等,这些信息被分散在很多地方进行管理,有一个你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的地方获取(打印)各种资料信息,最后到一个地方提交证明你的信息无误。(这样做的好处是管理责任划分明显,安全性高。)这种保存信息的方案,低效又不方便管理,以及日后的维护也是一个庞大的工作。

      这个和我们在应用开发中比较类似,如果你的状态信息是保存到多个Store对象中,那么之后的管理和维护等等都会变得特别困难,所以Vuex也使用了单一状态树来管理应用层级的全部状态。单一状态树能够让我们最直接的方法找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。

      2、getters基本使用

      有时候,我们需要从store中获取一些state变异后的状态,然后使用这个变异(就是做某些操作)的状态。

      例如基于之前counter例子,使用getters,操作counter变为平方后的值。

      同样地,getters内的方法也是有默认参数state。

      

      然后通过$store.getters.方法名调用。

      

       最后在页面也显示了正确的结果。

      

       总结:getters里面定义的方法是针对state的,虽然它在单个界面使用的时候,非常类似于计算属性。但是如果在多个界面使用时,getters的方法是比计算属性好得多,因为不需要在每个界面都定义和使用计算属性那么麻烦。(这更体现了公共管理state的思想,妙啊)

      此外,getters定义的方法定义中,除了可以传入state,也可以传入getters本身(将其作为方法中的参数)。

        假如我们需要带参数的getters方法,即可以返回一个函数,让这个函数带参数。注意,不能直接想之前一样简单的把参数放入getters方法函数中(因为其本身就有默认参数,放进去也是只是代替默认参数的名称而已,里面调用的还是默认参数,如state,getters等),这样不起作用。  

       

     

       当然也可以写成箭头函数的形式:

      3、mutations的携带参数

      Vuex的store状态的更新唯一方式:提交Mutation。($store.commit()方法)

      Mutation主要包括两部分:字符串的事件类型(type)一个回调函数(handler),该回调函数的第一个参数就是state。例如之前我们的举例中,increment是事件类型,具体的处理就是回调函数。(后一节有说这种格式的提交风格)

      在通过mutation更新数据的时候,有可能我们希望携带一些额外的参数。参数被称为是mutation的载荷payload)。

      mutations可以携带参数,在commit后面附上变量即可,然后在mutation对应的方法里面使用这个参数即可。例如只提交一个参数(变量,对象都行):(当传入多个变量时,可以写成一个对象)

       

      4、Mutation的提交风格

      上一小节,是通过commit进行提交时一种普通的方式。

      Vue还提供了另外一种风格,它是一个包含type属性的对象。此时,后面是一个payload对象,即下例中的count是一个对象。(此时代码写的就和之前不一样)

       (直接引用count是一个payload对象,调用值的话,写成count.count才合理(前一个count是形参,后者的count指的是原来的count值))

       所以应该写成这样比较合理:

       

      5、Mutation响应规则(数据的响应式原理)

       Vuex的store中的state是响应式的(源码中是通过Dep,Dep是data每个对象包括子对象都拥有一个该对象, 当所绑定的数据有变更时, 通过dep.notify()通知Watcher),当state中的数据发生改变时,Vue组件会自动更新。

      (简单来说,state中的属性都会被加入到响应式系统,而响应式系统会监听属性的变化,当属性发生变化时,会通知所有界面中用到该属性的地方,让界面发生刷新)

      这就要求我们必须遵守一些Vuex对应的规则:提前在store中初始化好所需的属性。当给state中的对象添加新的属性时,使用下面的方式:

      方式一:使用Vue.set(obj, 'newProp',123) 。这样做是响应式的,把在内部把‘newProp’也加入了响应式系统。

      删除属性时,用Vue.delete(obj, 'delProp') .

      方式二:用新对象给旧对象重新赋值

      注意,如果使用obj.newProp= 'xx',不是响应式的(因为之前没有这个obj.newProp的Dep)。此外,用delete方法删除属性也是非响应式的,因为这些方式不能加入到原来的响应式系统中。(这也是Vue响应式的内在要求,不仅是vuex,组件等等都是。)

      6、Mutation的类型常量

      在mutation中,我们定义了很多事件类型(也就是其中的方法名称)。当项目增大时,vuex管理的状态越来越多,需要更新状态的情况越来越多,那么意味这mutation的方法越来越多。使用者需要大量精力去记住这些方法,甚至在多个文件间来回切换,查看方法名称,很麻烦。

      也就是说,有时候我们需要记mutation的type,当定义和commit的时候都会用到,但是两边复制粘贴,太麻烦了。这时候,可以使用mutation的类型常量。

      首先,在store文件夹下,创建mutations-types.js文件。里面定义一些关于mutation类型的常量(并导出),例如下例,此时INCREMENT就相当于‘increment’。

       (index.js) 

       然后,在App.vue导入这个常量。(不是默认导出,记得用大括号哦)

      (App.vue)

       对应我们commit使用这个常量,就很简单了,不用来回看了。

      

       但是我们还得保证mutation定义的时候,方法名没有写错,所以,我们也把这个常量导入到index.js中。

      

       修改成['XX']的方式,然后用常量代替。

      

       

      7、actions的使用详解

      通常情况下,vuex要求我们mutation中的方法必须是同步的

      主要的原因是当我们使用devtools时,可以devtools可以帮助我们捕捉mutation的快照。但是如果是异步操作,那么devtools将不能很好地追踪这个操作什么时候会完成。

       所以不要在mutation中进行异步操作。

      但是在某些情况,我们确实想在vuex中进行一些异步操作,比如网络请求。

      action类似于mutation,但是是用来代替mutation进行异步操作的。

      action的基本使用:

      action中定义的方法也有默认参数,但不是state,而是context(上下文),目前可以理解为store。但注意修改state的唯一途径是通过mutation

      

       然后由于执行的是异步操作,对应的App.vue组件使用的方法也要修改。使用dispatch()(派遣)。

      

       此时,进行的异步操作可以被devtools捕获了。

      同样地,action也可以带参数的。

      (App.vue)

        (index.js)

       如果我们想在异步操作完成的时候,出现提示信息。可以结合使用Promise(ES6新增)。即把异步操作进行Promise封装。

      (index.js)

      然后在App.vue中使用then(),即执行异步请求成功后的操作。(相当于通过action中转,在返回Promise对象后使用then()函数)

       

      8、modules的使用

      Vue使用单一状态树,那么也意味着很多状态都会交给Vuex管理,当应用变得很复杂时,即写states,mutations,actions,getters代码过多时,会显得store对象比较臃肿。

      为解决这个问题,Vuex允许我们将store分割成模块(module),而每个模块拥有自己的states、mutations、actions、getters等。

      

       取模块中的某状态时,是使用store.state.a(a是在store中的模块名),如果进一步取模块a的state某属性,假如name,直接使用store.state.a.name即可,不需要写成store.state.a.state.name。

      在模块定义的mutation方法,在使用时,也是直接使用$state.commit('方法名')使用方法,其会先在store中的mutation搜索该方法,如果没有,则去模块中搜索,从而调用。所以模块的方法名最后不要和stroe的mutation方法重复。

      模块中的getters方法,也是类似于上述一样,直接通过普通的$store.getters.方法名来使用方法。

      然后,模块中的getters的方法可以想之前说的一样,使用当前getters作为方法参数。

      此外,模块中的getters的方法还可以有第三个默认参数,叫rootState,特指源store的state。

      模块中的actions。之前提过,actions中的方法,里面有一个默认参数,即context(上下文),但注意,此时store.commit(),即context.commit(),这个store是模块自己的store。但是这个context里面有很多属性,包括根store和根getters。 

      9、store文件夹的目录结构

      当我们的vuex帮助我们管理过多的内容时,好的项目结构可以让我们的代码更加清晰。

     

       之前我们把所有关于vuex的代码写到一块了,当项目比较大时,不方便管理,所以需要进行构造好的目录结构,即对一些代码进行抽离。

      state代码:(index.js里面)把state抽离成一个对象,放在store外面,然后在里面使用这个state对象。

      

       mutation:(重新创建一个mutations.js文件,在store目录下)

      然后把index.js中的mutation对象写进去,再导出。最后在index.js中引用。

      actions:也是类似上述的做法。(actions.js)

      getters:也是类似上述的做法。(getters.js)

      modules:新建一个modules文件夹(store目录下),由于模块可以有多个,然后在这个modules文件夹放置一个一个模块文件(.js文件,也是导出),最后在index.js按需引用(但引用的时候,最好是a: moduleA,给moduleA一个名字a)。

  • 相关阅读:
    SQL Azure (17) SQL Azure V12
    Microsoft Azure News(5) Azure新DV2系列虚拟机上线
    Azure Redis Cache (3) 在Windows 环境下使用Redis Benchmark
    Azure PowerShell (11) 使用自定义虚拟机镜像模板,创建Azure虚拟机并绑定公网IP(VIP)和内网IP(DIP)
    Windows Azure Virtual Machine (31) 迁移Azure虚拟机
    Windows Azure Web Site (16) Azure Web Site HTTPS
    Azure China (12) 域名备案问题
    一分钟快速入门openstack
    管理员必备的Linux系统监控工具
    Keepalived+Nginx实现高可用和双主节点负载均衡
  • 原文地址:https://www.cnblogs.com/xinkuiwu/p/12115274.html
Copyright © 2020-2023  润新知