# 起步

Vuex

官方解释:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。

它采用 集中式存储管理 应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。

状态管理

可以简单的将其看成把需要多个组件共享的变量全部存储在一个对象里面。

然后,将这个对象放在顶层的Vue实例中,让其他组件可以使用。 那么,多个组件就可以共享这个对象中的所有变量属性

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

# 单页面状态管理

单页面状态管理

State:不用多说,就是我们的状态。(姑且可以当做就是data中的属性)

View:视图层,可以针对State的变化,显示不同的信息.

Actions:这里的Actions主要是用户的各种操作:点击、输入等等,会导致状态的改变。

在项目根目录安装Vuex

npm install vuex --save
1

在组件文件夹新建一个HeeloVuex.vue,在src文件夹下新建一个store文件夹,新建一个index.js,

下载完毕后在main.js下导入vuex

在store文件夹下index.js配置Vuex

此时的HelloVuex跟App很明显的形成了父子关系,App里面的数据counter,想要在HelloVuex里面用的话,目前还没有什么好的解决方案,只有父传子的通信可以解决,暂且可以不把它们当成父子关系,它们之间是相互独立的房间(兄弟关系),都需要使用counter这个数据(变量)

index.js

HeeloVuex组件

App组件

页面展示效果,点击增加和减少App和HelloVuex的内容都会改变,实现了用Vuex的状态管理管理了相同需要的变量couter

这就是最基本的Vuex思想,但是这种方式是不好的,Vue官方推出了一个浏览器插件,Devtoods,该工具可以在浏览器端进行调试,但是如果使用了该方法(只修改State状态),该工具就会起不到作用.(不能同步)

# Vuex状态管理图例

通过Mutations更改State的状态,需要有异步操作的时候需要用到Actions

还是刚才的案例

# Vuex核心概念

State Getters Mutations Actions Module

# state单一状态树

Vuex提出使用单一状态树, 什么是单一状态树呢?英文名称是Single Source of Truth,也可以翻译成单一数据源。

举个例子: 在国内我们有很多的信息需要被记录,比如上学时的个人档案,工作后的社保记录,公积金记录,结婚后的婚姻信息,以及其他相关的户口、医疗、文凭、房产记录等等(还有很多信息)。 这些信息被分散在很多地方进行管理,有一天你需要办某个业务时(比如入户某个城市),你会发现你需要到各个对应的工作地点去打印、盖章各种资料信息,最后到一个地方提交证明你的信息无误。 这种保存信息的方案,不仅仅低效,而且不方便管理,以及日后的维护也是一个庞大的工作(需要大量的各个部门的人力来维护,当然国家目前已经在完善我们的这个系统了)。

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

简而言之,就是把把所有的状态信息都保存在一个store对象里面

# Getters基本使用

类似于组件内的getter属性,用于写计算类的方法

最终页面展示效果如下

# Getters传参

现在多了一个需求,就是在筛选过后的数据里,要显示学生的个数,此时就可以再定一个getters的方法,more18stuLength,如果还像上面一样用filter筛选数据的话会显得比较麻烦.所以此时可以传递一个参数

使用

效果

如果还像传参,需要用户来判断筛选年龄大于20的学生

使用

<h2>{{$store.getters.moreAgestu(20)}}</h2>
1

效果

# Mutation状态更新

Vuex的store状态的更新唯一方式:提交Mutation

Mutation主要包括两部分

字符串的事件类型(type)(可以理解为函数名字)

一个回调函数(handler),该回调函数的第一个参数就是state(可以理解为函数体)

mutation的定义方式

mutations:{
    increment(state){
        state.counter++
    }
}
1
2
3
4
5

通过mutation更新

methods: {
    addition() {
    this.$store.commit("increment");
    }
},
1
2
3
4
5

# Mutation传递参数

在通过mutation更新数据的时候, 有可能我们希望携带一些额外的参数

参数被称为是mutation的载荷(Payload)

上面的例子说到增加count变量的数量,减少count变量的数量,getter属性的用途,(平方,筛选学生),现在叕叕叕叕增加了一个需求,需要每次点击按钮,count值+5,+10.这个时候就需要在Mutation传递参数了,如果参数不是一个,并且有多个参数传递,通常以对象的形式传递,也就是说Payload是一个对象(需要添加一个学生进来)

# Mutation提交风格

Vue还提供了另外一种风格, 它是一个包含type属性的对象

界面显示效果也是一样的

# Mutation响应规则

Vuex的store中的state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新.

一开始在state里面定义的属性,都会被加入到响应式系统中,而响应式系统会监听属性的变化,当属性发生变化时,会通知所有界面中用到该属性的地方,让界面发生刷新

当给state中的对象添加新属性时, 使用下面的方式: 方式一: 使用Vue.set(obj, 'newProp', 123) 方式二: 用新对象给旧对象重新赋值

# Mutation常量类型

在mutation中, 我们定义了很多事件类型(也就是其中的方法名称). 当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多. 方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.

创建一个文件: mutationstypes.js, 并且在其中定义我们的常量

# Mutations同步函数

通常情况下, Vuex要求我们Mutation中的方法必须是同步方法. 主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照. 但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成,比如settimeout,就是异步操作,实际上数据已经更改了,但是devtools的state数据还没更改.

# actions

我们强调, 不要再Mutation中进行异步操作. 但是某些情况, 我们确实希望在Vuex中进行一些异步操作, 比如网络请求, 必然是异步的.

Action类似于Mutation, 但是是用来代替Mutation进行异步操作的.

context是和store对象具有相同方法和属性的对象. 也就是说, 我们可以通过context去进行commit相关的操作, 也可以获取context.state等.

在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch

# Module

Module是模块的意思, 为什么在Vuex中我们要使用模块呢?

Vue使用单一状态树,那么也意味着很多状态都会交给Vuex来管理.当应用变得非常复杂时,store对象就有可能变得相当臃肿.

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

# 项目结构组织

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