本节主要介绍 Vuex 的基本概念,并一步步引导读者如何去运用 Vuex 在一个应用中,以浅显易懂的例子掌握 Vuex 的核心知识。
# 什么是 Vuex?
首先我们要弄清楚 Vuex 是做什么的?为什么使用 Vuex ?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。uniapp集成了vuex的状态管理功能,可以在多端情况下使用。
Vuex 需要解决的问题:
- 多个视图依赖于同一状态。比如当前音乐应用的账号页,我的页面保持登录状态以及用户信息。
- 来自不同视图的行为需要变更同一状态。比如登录页更改登录状态,账号页面退出登录改成未登录状态。
这个状态自管理应用包含以下几个部分:
- state,驱动应用的数据源;
- view,以声明方式将 state 映射到视图;
- actions,响应在 view 上的用户输入导致的状态变化。

上面的概念比较模糊,我们先来点简单的。
在这引用了一位技术大拿关于管理状态(state)的讲解:
不管是 Vue ,还是 React,都需要管理状态(state),比如组件之间都有共享状态的需要。什么是共享状态?比如一个组件需要使用另一个组件的状态,或者一个组件需要改变另一个组件的状态,都是共享状态。
父子组件之间,兄弟组件之间共享状态,往往需要写很多没有必要的代码,比如把状态提升到父组件里,或者给兄弟组件写一个父组件,听听就觉得挺啰嗦。
如果不对状态进行有效的管理,状态在什么时候,由于什么原因,如何变化就会不受控制,就很难跟踪和测试了。如果没有经历过这方面的困扰,可以简单理解为会搞得很乱就对了。
在软件开发里,有些通用的思想,比如隔离变化,约定优于配置等,隔离变化就是说做好抽象,把一些容易变化的地方找到共性,隔离出来,不要去影响其他的代码。约定优于配置就是很多东西我们不一定要写一大堆的配置,比如我们几个人约定,view 文件夹里只能放视图,不能放过滤器,过滤器必须放到 filter 文件夹里,那这就是一种约定,约定好之后,我们就不用写一大堆配置文件了,我们要找所有的视图,直接从 view 文件夹里找就行。
根据这些思想,对于状态管理的解决思路就是:把组件之间需要共享的状态抽取出来,遵循特定的约定,统一来管理,让状态的变化可以预测。根据这个思路,产生了很多的模式和库。
Vuex 防止随意修改而不好跟踪状态,规定组件不允许直接修改 store 实例的 state,组件必须通过 action 来改变 state ,也就是说,组件里面应该执行 action 来分发 (dispatch) 事件通知 store 去改变。这样约定的好处是,我们能够记录所有 store 中发生的 state 改变,同时实现能做到记录变更 (mutation)、保存状态快照、历史回滚的先进的调试工具。
# Vuex 的基础使用(创建一个改变登录状态的应用)
我们一个简单的登录状态的应用开始。
第一步,创建 store ;
首先在根目录下新建文件夹 store,并创建 index.js :
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
isLogin: false // 是否登录的状态,默认为未登录 false
},
mutations: {
// 定义一个操作isLogin状态的方法
storeLogin (state) {
state.isLogin = true
}
}
})
export default store
上面代码引入了 vue,vuex ,并使用 Vue.use(Vuex) 安装Vuex插件,在 new Vuex.Store 传参对象中定义 state ,mutations 。
我在上面定义了 isLogin,整个项目以这个变量作为登录标记,storeLogin 的方法来修改 isLogin 值,而且修改 isLogin 值只能通过 storeLogin 方法。
第二步,新建登录页login.vue;
在 pages 下新建一个页面 login.vue,鼠标悬浮在当前项目目录下选择【新建页面】,命名为 login 勾选【自动在 pages.json 中注册】:
上面新建了一个 login 路由页面,勾选【自动在 pages.json 中注册】是在 pages.json 文件中注册页面路由,在 HBuilder 上部操作 【运行】>>【运行到浏览器】>> 选择一个浏览器,这样客户端就能以 http://localhost:8080/#/pages/login/login 访问。
第三步,引入 Vuex ;
在主入口 main.js 引入刚才新建的 store:
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.prototype.$store = store
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
使用
Vue.prototype.$store = store把store挂在到Vue中,这样整个项目就可以共享这个$store状态,通过在根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过this.$store访问到。下面要在 login.vue 页面共享isLogin登录状态;
<!-- login.vue -->
<template>
<view>
登录状态: {{$store.state.isLogin}}
</view>
</template>
<script>
export default {
