本文章节如下
- 首先先来看看
Vuex的整体流程 - 然后介绍一些比较常见的
API的用法 - 最后则是介绍一下初始化装载与注入的过程
至于源码的部分,则是会下一篇章节当中来进行介绍
流程图
Vuex 的整个执行流程如下(转自网络)

Vuex 为 Vue Components 建立起了一个完整的生态圈,包括开发中的 API 调用一环,围绕这个生态圈,简要介绍一下各模块在核心流程中的主要功能
Vue ComponentsVue组件,HTML页面上负责接收用户操作等交互行为- 执行
dispatch方法触发对应action进行回应
dispatch- 操作行为触发方法,是唯一能执行
action的方法
- 操作行为触发方法,是唯一能执行
actions- 操作行为处理模块,负责处理
Vue Components接收到的所有交互行为,包含同步或者异步的操作 - 支持多个同名方法,按照注册的顺序依次触发,向后台
API请求的操作就在这个模块中进行,包括触发其他action以及提交mutation的操作 - 该模块提供了
Promise的封装,以支持action的链式触发
- 操作行为处理模块,负责处理
commit- 状态改变提交操作方法,对
mutation进行提交 - 是唯一能执行
mutation的方法
- 状态改变提交操作方法,对
mutations- 状态改变操作方法,是
Vuex修改state的唯一推荐方法,其他修改方式在严格模式下将会报错 - 该方法只能进行同步操作,且方法名只能全局唯一,操作之中会有一些
Hook暴露出来,以进行state的监控等
- 状态改变操作方法,是
state- 页面状态管理容器对象,集中存储
Vue components中data对象的零散数据 - 全局唯一,以进行统一的状态管理,页面显示所需的数据从该对象中进行读取,利用
Vue的细粒度数据响应机制来进行高效的状态更新
- 页面状态管理容器对象,集中存储
gettersstate对象读取方法,图中没有单独列出该模块,应该被包含在了render中Vue Components通过该方法读取全局state对象
总结如下
Vue组件接收交互行为,调用dispatch方法触发action相关处理- 若页面状态需要改变,则调用
commit方法提交mutation修改state - 通过
getters获取到state新值,重新渲染Vue Components,界面随之更新
目录结构

| 目录 | 介绍 |
|---|---|
module |
提供 module 对象与 module 对象树的创建功能 |
plugins |
提供开发辅助插件,如时光穿梭功能,state 修改的日志记录功能等 |
helpers.js |
提供 action、mutations 以及 getters 的查找 API |
index.js |
是源码主入口文件,提供 store 的各 module 构建安装 |
mixin.js |
提供了 store 在 Vue 实例上的装载注入 |
util.js |
提供了工具方法如 find、deepCopy、forEachValue 以及 assert 等方法 |
下面我们就来看看其中的一些 API 的用法,比如之前介绍过的 State,Getter,Mutation 和 action 等,Vuex 使用单一状态树,每个应用将仅仅包含一个 store 实例,从 store 实例中读取状态最简单的方式就是在计算属性当中返回某个状态
State
Vuex 通过 store 选中,将状态从根组件注入到每一个子组件当中
1 | new Vue({ |
子组件可以通过 this.$store 访问到该 store 的实例
1 | const Counter = { |
Getter
简单的来说,可以将其理解为 store 的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算,它接收 state 作为『第一个参数』
1 | const store = new Vuex.store({ |
外部调用
1 | store.getters.doneTodos // [{ id: 1, text: '...', done: true }] |
也可以接受其他的 getter 作为『第二个参数』
1 | getters: { |
也可以返回一个函数,来实现给 getter 传参
1 | getters: { |
Mutation
更改 Vuex 的 store 中的状态的唯一方法就是提交 mutation,非常类似于事件
- 每个
mutation都有一个事件类型(type)和一个回调函数(handler) - 回调函数就是进行状态更改的地方,并且接收
state作为第一个参数
1 | const store = new Vuex.Store({ |
需要注意
- 不能直接调用
mutation handle - 应当以相应的
type调用store.commit方法
1 | store.commit('increment') |
同时可以向 store.commit 传入额外的参数,即 mutation 的载荷(payload)
1 | // ... |
Mutation 的提交
- 必须是同步函数(若是异步,则可能存在当
mutation触发的时候,回调函数还没有被调用的情况) mutation的提交可以使用this.$store.commit('...')- 或者可以使用
mapMutations辅助函数将组建中的methods映射为store.commit调用,如下所示
1 | import { mapMutations } from 'Vuex'; |
Action
- 提交的是
mutation,而不是直接变更状态 - 可以包含任意异步操作
一个简单的 action
1 | const store = new Vuex.store({ |
action 函数接受一个与 store 实例具有相同方法和属性的 Context 对象,因此可以调用 context.commit 提交一个 mutation
分发 Action
action 通过 store.dispatch 方法触发
1 | store.dispatch('increment') |
之所以这样使用,是因为 mutation 必须同步执行,而 action 则不必如此,可以在其内部执行异步操作
1 | actions: { |
组件当中 Action 的分发
同 Mutation 类似,可以使用 this.$store.dispatch('...') 或者使用 mapActions 辅助函数
组合 Action
因为 store.dispatch 返回的是一个 Promise 对象,所以可以使用 then() 方法来进行处理,亦或是可以使用 async/await
1 | // 假设 gotData() 与 gotOtherData() 均返回 Promise |
初始化装载与注入
下面我们就来看看 Vuex 到底是如何在项目当中进行装载与注入的,首先是入口文件,先来看入口处的 export 函数到底导出了哪些东西,详细可以见官方 vuejs/vuex
需要注意的是,可能版本不同而导致内容有所不同,但是我们关心的仅仅是几个核心方法
1 | // https://github.com/vuejs/vuex/blob/dev/src/index.js |
装载与注入
我们一般在使用 Vuex 的时候如下所示
1 | // store.js |
除了 Vue 的初始化代码,只是多了一个 store 对象的传入,我们来看下源码中的实现方式
1 | // store.js |
若是首次加载,将局部 Vue 变量赋值为全局的 Vue 对象,并执行 applyMixin 方法
1 | // store.js |
下面是 applyMixin 的源码,如果是 2.x 以上的版本,可以使用 Hook 的形式进行注入,即在 beforeCreated 钩子前插入初始化代码(vuexInit)
1 | export default function (Vue) { |
这也就是为什么我们在 Vue 的组件中可以通过 this.$store.xxx 来访问到 Vuex 的各种数据和状态的原因了,因为在任意组件中执行 this.$store 都能找到装载的那个 store 对象,如下图所示,页面的结构为

对应的 store 流向
