手把手学习Vue3.0:Vuex4.x集成+使用理论总结大全

1,144 阅读6分钟

背景

我在做一个页面效果,就是在首页上点击导航,或者其他的按钮需要在主显示区域创建一个tab,同时也要与面包屑的效果。开始我没有开通菜单的router效果,仅仅是利用菜单组价的点击事件做出了想要的效果,使用的是事件总线传参,因为事件总线可以在任何组件间传递参数,事件总线的使用可以参考我的《手把手学习Vue3.0:Vue3.0正确使用Bus总线mitt实现组件间通信和传参》。事件总线的特点是在事件发起的地方挂载事件,在需要跟随变化的接收方监听事件。之所以选择vuex是因为我发现时间总线方式在实现复杂场景的时候有弊端,下面跟我一起看看怎么使用vuex。

放弃总线的原因 

还以我的页面效果举例子:

  1. 由于菜单组件开通了路由功能,所以每次点击操作有路由的更新
  2. tab组件和面包屑组件依赖菜单的变化,同时面包屑和tab组件还需要其他的属性才能实现效果
  3. 档切换tab的时候菜单和面包屑都要做相应的变化,这个时候就会多写事件,代码已经开始不美观,非结构性的代码开始出现了,不利于维护,场景越复杂就越乱。
  4. 而事件本身就是一个很纯粹的操作,为了实现效果事件变得不纯粹。
  5. 参数传递存在局限性,监听组件需要的参数不同

基于以上几点我觉得vuex更适合这样的场景,vuex是集中管理,全局单例唯一,而且vue将状态从根组件“注入”到每一个子组件中,使用起来非常方便。

Vuex的学习方法

vue3.x对应的vuex4.x版本,目前看还是纯英文网站,我推荐的学习方法是:

  • 大家对照着3.x的中文文档先学会vuex有什么,怎么使用。
  • 一定要从头到尾把3.x的中文档看完,并总结出自己的理解
  • 3.x的目录跟4.x的目录是想对应的,大部分是相同的,差异化的可以直接翻译,英文好的直接读,不好的也可以读读看,锻炼下自己也可以。

  • 代码部分直接看4.x,代码部分谁都能看的懂,有差别的地方格外注意下就OK。

  • 时间长了,多看几遍英文也就那么回事了,最主要的有中英文对照,可以免费学英文。
  • 一定要动手去尝试,哪怕出错也没关系,不动手永远不知道怎么运行时对的。手白了谁动手了,代码就是谁的。动手的根没有动手的差别非常大,尤其是一个人负责整个项目的时候。

Vuex的核心思想

状态管理的核心是如下三方面:

  • state,驱动应用的数据源;
  • view,以声明方式将 state 映射到视图;
  • actions,响应在 view 上的用户输入导致的状态变化。

接下来我谈一下个人对这三个核心的理解:

  • state,就是我们交给vuex管理的全局数据
  • view,就是把vuex中的state跟页面渲染绑定
  • actions,就是操作state的API

按我的转义,大家心里可以有一个简单的整体理解,就是vuex提供放数据的地方,这些数据不推荐直接取,而是用它推荐的API去操作,像绑定其他变量一样使用,页面自动渲染。 实战分解部分,我会讲清楚,state写在什么地方,vuex的index.js里都提供什么,我们的组件中怎么使用。

Vuex的集成

  • 单独安装命令
npm install vuex@next --save
  •  如果是用cli脚手架生成的项目会自动集成,通常都在store目录下。

  • index.js代码如下:

state:存在状态,数据区

mutations:更改state的唯一途径,定义提交commit的方法,所有的mutations都是同步方法

actions:提交mutation,不直接变更状态state,而是由mutation在更改state,action中可以包含异步操作,action可以组合和调用其他action,相当于把state的commit也管理起来了。对于使用state的组件来说关于state的使用都由vex独立管理起来。

modules:模块或者分组,如果项目很大,要vuex管理的状态很多,都写到一个文件有点臃肿,这个时候分不同的模块,单个文件就非常小,而且单一集中更好管理。一般情况下都写在index.js中就够了。

  • 在main.js中引入store

  • 以上代码都是脚手架自动生成的,直接拿来用就可以了,我的这些都是最新版本基于vue3.0的,cli4以后的。
  • 到此vuex的集成就结束了。

Vuex的实战分解

实战我从两个方面讲解,一是vuex中都定义什么(即store中怎么编码),而是组件中都怎么使用。这些写法都是固定的套路,大家先背过,后面想怎么写就怎么写。

1.store中的固定写法:

import { createStore } from "vuex";

export default createStore({
  state: {
    todos: [
      { id: 1, text: "...", done: true },
      { id: 2, text: "...", done: false }
    ],
    count: 0
  },
  getters: {
    doneTodos(state) {
      return state.todos.filter(todo => todo.done);
    }
  },
  mutations: {
    increment(state) {
      // mutate state
      state.count++;
    }
  },
  actions: {
    increment(context) {
      context.commit("increment");
    }
  },
  modules: {}
});
  • state定义了两个状态todos、count
  • getters是通过Getter 属性访问状态,这里可以包含一些逻辑,这里只有读,没有更新。在使用组件中Getter会缓存和同步更新。
  • mutations是所有操作的定义,唯一途径。通过commit来调用
  • actions是封装commit的抽象,这样commit对组件使用也透明了。
  • modules暂时先不用关心,只是对store的切割,用法不变。
  • 如果有面向对象的思维,就是数据定义和操作都给你封装好了,外部使用直接调用API即可,不需要关注内部细节,也不需要外部直接操作store。

2.组件中的具体使用写法:

  • 在计算属性中获取状态值。这个时候上面定义的Getter就起作用了,可以使用辅助函数mapState、mapGetters。vuex4.x跟vuex3.x在这块的代码一样没区别。

​​​​​​​     

  • 在任意method中可以提交更改,这是调用上面的action,通过 store.dispatch 方法触发,可以使用辅助函数mapActions

​​​​​​​   

  • 如果上面没有定义上action,那么可以使用mapMutations,但是不推荐使用

​​​​​​​

  • 实际使用中都是使用辅助函数+简写的方式,这样代码简洁,易于维护,推荐的方式

总结

  • 一定要遵守约定由于配置的思想,让代码更优雅
  • vuex的使用可以用来那个句话来说:1.store中写state、getters、mutations、actions。2.组件中使用辅助函数来获取和提交mapState、mapGetters、 mapMutations、 mapActions
  • 庖丁解牛般的拆开了揉碎了,再拼起来,vuex怎么和其他的核心组件组合使用就一目了然了,而且也可以做到熟记于心。
  • 如果不把核心抽象出来,脑子还是一锅粥,似乎理解,但又不知道从哪里开始说,或者组织不出有效的话语一下说清楚。
  • 我的这篇文章就是要解决这个问题。这里的代码都是官方的例子,后面我会把我的代码开源出来。
  • 如果喜欢一键三联,评论、点赞、加关注。