Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。在学习 Vue.js 时,大家一定知道在 Vue 中各个组件之间传值的痛苦,在 Vue 中我们可 以使用 Vuex 来保存我们需要管理的状态值,值一旦被修改,所有引用该值的地方就会自动更新。
Vuex 是适用于在 Vue 项目开发时使用的状态管理工具。试想一下,如果在一个项目开 发中频繁的使用组件传参的方式来同步 data 中的值,一旦项目变得很庞大,管理和维护这 些值将是相当棘手的工作。
状态管理:简单理解就是统一管理和维护各个 vue 组件的可变化状态(你可以理解成 Vue 组件里的某些 data )。
让我们从一个简单的 Vue 计数应用开始,代码如下:
//src/components/count.vue
<template>
<div>
<!-- view -->
<div>{{ count }}</div>
button @click="increment">increment</button>
</div>
</template>
<script>
export default {
// state
data () {
return {
count: 0
}
},
// actions
methods: {
increment () {
this.count++
}
}}
</script>
这个状态管理应用包含以下几个部分:
State:驱动应用的数据源,通常用在 data。
View:以声明方式将 state 映射到视图,通常用在 template。
Actions:响应在 view 上的用户输入导致的状态变化,即通过方法对数据进
行操作, 通常用 methods。

这里的数据 count 和方法 increment 只有在 count.vue 组件里可以访问和使用,其他的组 件是无法读取和修改 count 的。但是,当我们的应用遇到多个组件共享状态时,单向数据流 的简洁性很容易被破坏。
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
这就是 Vuex 背后的基本思想,Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新

注意:使用Vuex会有一定的门槛和复杂性,它的主要使用场景是大型单页应用,更适合多人协同开发
1.安装 首先通过 NPM 安装 Vuex 依赖,命令如下:
npm install vuex --save
2.使用
(1)在项目根目录创建 store 文件夹,在该文件夹下创建 index.js,代码如下:
import Vue from 'vue' //store/index.js
import Vuex from 'vuex'
//挂载
Vuex Vue.use(Vuex)
//创建 VueX 对象
const store = new Vuex.Store({
state:{
//存放的键值对就是所要管理的状态
name:'这是 Vuex 的第一个数据'
}})
//导出
store export default store
(2)在 main.js 文件中将 store 挂载到当前项目的 Vue 实例中去,代码如下:
//main.js 部分代码省略
import store from './store'//导入 store,自动会寻找 index.js
new Vue({
el: '#app',
router,
store, //store:store 和 router 一样,将我们创建的 Vuex 实例挂载到这个 vue 实例中
components: { App },
template: '<App/>'
})
(3)在组件中使用 Vuex,如在 HelloWorld.vue 中,我们要将 state 中定义的 name 拿来 在 h1 标签中显示,代码如下:
<template>
<div id="hello">
name:
<h1>{{ $store.state.name }}</h1><!--获取 state 中的值-->
</div>
</template>
在 VueX 对象中,其实不止有 state,还有用来操作 state 中数据的方法集,以及当我们 需要对 state 中的数据需要加工的方法集等成员。成员列表如下:
State:数据源存放状态。
mutations state:成员操作。
Getters:加工 state 成员给外界。
Actions:异步操作。
Modules:模块化状态管理。
(1)Mutations:mutations 是操作 state 数据的方法的集合,比如对该数据的修改、增 加、删除等。
mutations 方法有默认的形参([state] [,payload]):
state 是当前 VueX 对象中的 state 。
payload 是该方法在被调用时传递参数使用的。
例如编写一个方法,当被执行时,把 state 中管理的 name 值修改成“beixi”,代码如下:
//store/index.js 部分代码省略
const store = new Vuex.Store({
state:{
name:'helloVueX'//存放的键值对就是所要管理的状态
},
mutations:{
edit(state){//es6 语法,等同 edit:funcion(){...}
state.name = 'beixi'
}
}
})
而在组件中,我们需要去调用 mutation,例如在 HelloWorld.vue 的任意方法中调用,代码如下:
//HelloWorld.vue 部分代码省略
<button @click="edit">获取修改后数据</button>
export default {
methods: {
edit(){
this.$store.commit('edit')
}
}}
(2)Mutation 传值:在实际生产过程中,需要在提交某个 mutation 时携带一些参数给方法使用。
单个值提交时,代码如下:
this.$store.commit('edit',18)
当需要多参提交时,推荐把他们放在一个对象中来提交,代码如下:
this.$store.commit('edit',{age:18,sex:'男'})
在 HelloWorld.vue 页面方法中接收挂载的参数,代码如下:
edit(state,payload){
state.name = 'beixi'
console.log(payload) // 18 或{age:18,sex:'男'}
}
(3)增删 state 中的成员
为了配合 Vue 的响应式数据,我们在 Mutations 的方法中,应当使用 Vue 提供的方法来 进行操作。如果使用 delete 或者 xx.xx = xx 的形式去删或增,则 Vue 不能对数据进行实时响应。
Vue.set 为某个对象成员设置值,若不存在则新增。例如对 state 对象中添加一个 age 成员,
代码如下:
Vue.set(state,"age",18)
Vue.delete 删除成员,将刚刚添加的 age 成员删除,代码如下:
Vue.delete(state,'age')
(4)Getters:相当于 Vue 中的 computed 计算属性,getter 的返回值会根据它的依赖被 缓存起来,且只有当它的依赖值发生了改变才会被重新计算,这里我们可以通过定义 Vuex 的 Getter 来获取,Getters 可以用于监听、state 中的值的变化,返回计算后的结果。
Getters 中的方法有两个默认参数:
state 当前 VueX 对象中的状态对象。
getters 当前 getters 对象,用于将 getters 下的其他 getter 拿来用,如下面代码所示:
//store/index.js 部分代码省略
const store = new Vuex.Store({
//...
getters:{
nameInfo(state){
return "姓名:"+state.name
},
fullInfo(state,getters){
return getters.nameInfo+' 年龄:'+state.age
}
}
})
HelloWorld.vue 组件中调用,代码如下:
<div id="hello">
<h3>从 Getters 获取计算后的值:{{this.$store.getters.fullInfo}}</h3>
</div>
(5)Actions:由于直接在 mutation 方法中进行异步操作,将会引起数据失效。所以提 供了 Actions 来专门进行异步操作,最终提交 mutation 方法。
Actions 中的方法有两个默认参数:
context 上下文(相当于箭头函数中的 this)对象。
payload 挂载参数。
例如我们在两秒后执行 mutations 中的 edit 方法,由于 setTimeout 是异步操作,所以需 要使用 actions,代码如下:
//store/index.js 部分代码省略
const store = new Vuex.Store({
//...
actions:{
aEdit(context,payload){
setTimeout(()=>{
context.commit('edit',payload)
},2000)
}
}
})
在 HelloWorld.vue 组件中调用,代码如下:
//HelloWorld.vue 部分代码省略
<button @click="aEdit">异步获取数据</button>
export default {
methods: {
aEdit(){
this.$store.dispatch('aEdit',{age:18})
}
}}
对上述代码进行改进,由于是异步操作,所以我们可以为我们的异步操作封装为一个 Promise 对象,代码如下:
aEdit(context,payload){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
context.commit('edit',payload)
resolve()
},2000)
})
}