声明:本章内容属于本人发布到GitChat平台中《深入浅出学习Vue开发》中的部分内容,在争取了发布平台的同意之后,才发布于慕课网。
这一章我们来学习Vuex,如果要学习好Vuex那么最最重要的就是要知道Vuex是干嘛的,我们为什么需要Vuex。因为对于Vuex来说,它的使用方式非常简单,知识点也不多。Vuex唯一的难点就是很多人无法理解它。所以在本章我们会着重的讲解Vuex的作用,我们为什么需要它,在理解了这些之后,我们再去学习Vuex的使用就会水到渠成了。
状态管理我们直接来看这一段代码:
在这段代码中,我们期望能够通过点击com-1中的count++按钮来改变com-2中的count,使其每点击一下自加一。基于这个需求我们应该如何去实现呢?基于我们现在所学到的知识,一共有两种解决办法,我们来看一下。
第一种解决方案就是:通过组件传参的方式。我们知道在Vue中,兄弟组件是没有办法进行传参操作的,那么按照我们现在所学到的知识,如果希望通过组件间传参的方式解决这个问题,那么就需要对我们的html结构进行一下修改,我们看下面的代码:
在上面的代码中我们把com-2变成了com-1的一个子组件,当我们点击count++按钮的时候,我们通过props向com-2中传递了count的值,我们在学习组件的时候学习过 当我们使用prop进行参数传递的时候,父组件数据的改变会影响子组件 。这样,我们在com-1中count的变化就会在com-2中被展示出来。
在我们的Demo事例中,通过这种方法来维护count的状态未尝不可。不过大家想一下,在我们的实际项目中各个组件的层级会变得非常复杂,同时对于这种数据的状态管理如果都通过这种组件之间传参的方式来进行解决的话,则会变得非常难以维护。那么我们就会想有没有其他的方式可以解决这个问题?那就是采用全局状态管理的方法。
我们看一下下面的代码:
我们看到在上面的代码中我们维护了一个store对象,用作两个组件中原始数据对象的实际来源 当访问数据对象时,一个 Vue 实例(组件实例)只是简单的代理访问。 所以,如果你有一处需要被多个实例间共享的状态,可以简单地通过维护一份数据来实现共享。现在当 store 发生变化,com-1和com-2 都将自动的更新引用它们的视图。从而达到了我们需求,当我们在com-1中点击count++的时候在com-2中展示count的值。
但是对我们现在的代码来说,依然存在一个非常致命的问题,那就是 在任何时间,我们应用中的任何部分,在任何数据改变后,都不会留下变更过的记录。这在我们想要进行代码调试的时候,将会变成一个噩梦。所以我们可以采用一个简单的store模式来解决这个问题:
在上面的代码中我们为store增加了debug、state、mutation三个属性,state是store对象中所有状态数据的描述,当state中的数据想要发生改变的时候都要通过mutation来进行。比如我们的count++的点击事件,则是通过调用store.mutation.addCount方法进行,以此来记录数据的改变。
这样的一种方式在Vue中被称为**store模式**,我们使用**store模式作为我们整个项目的状态管理器**,但是当我们的项目变得越来越大,越来越复杂的时候,我们更需要一个更加专业,更加全面的状态管理器,那么这个状态管理器就是Vuex。
VuexVuex继承了store模式的思想,并做了更多的扩展,提供了更多的功能。我们先来看一下Vuex的定义:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。致力于管理项目中所有公用数据的状态。
我们参照上面的几个例子,是不是对Vuex的定义更加容易理解。Vuex是在store模式上的扩展,它们拥有相同的思想。我们看一下Vuex中的核心功能。
1、State :Vuex中的 “ 唯一数据源 ”
2、Getter :Vuex 中的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
3、Mutation :更改Vuex中数据的唯一方式,就是通过mutation进行修改,只支持同步操作。就像我们上面的例子一样。
4、Action :当我们需要异步更改数据时,通过 Action 提交的是 mutation,而不是直接变更状态。
5、Module : 由于Vuex使用单一状态树,应用的所有状态会集中到一个比较大的对象。Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter甚至是嵌套子模块——从上至下进行同样方式的分割。
由前面的例子我们也可以看出,我们不希望state中的状态被直接改变(虽然我们可以这么做),而是期望把Mutation作为改变state的唯一方式,而当我们必须要通过异步来改变状态的时候,我们期望使用action来提交mutaion用于改变状态。大家思考一下Vuex为什么要这么去设计呢?
在Vuex中说白了,任何的操作都是围绕state来进行的,Vuex是状态管理器,作用就是管理state中的状态,其他提供的所有功能Getter、Mutation、Action都是为了能够更好的管理state,而之所以设计成期望通过Mutation改变状态,是因为我们期望**所有状态的变化都是有迹可循的!**我们通过一个图示来看一下Vuex的设计流程(图示来自Vuex官网):
图示完美的解释了Vuex的执行流程:我们在Vue的组件中提交Dispatch操作,用以操作对应的Actions方法,然后在Actions的方法中,通过提交Commit操作调用对应的Mutation方法来修改对应的状态State,最后State的改变被渲染到我们的组件中。这就是Vuex的整个核心流程,我们通过一段代码来描述一下:
在上面的代码中,我们首先通过new Vuex.Store去声明了一个Vuex的实例store ,当我们点击count++按钮的时候,调用this.$store.dispatch('increment', 1);其实是调用了Vuex中actions中定义的increment方法,在这个方法中我们声明了一个setTimeout,指定在1秒钟之后执行context.commit('increment', num)方法,调用mutation的increment方法,然后我们在mutation的increment方法中修改了state中的count的值,使其state.count += num;。这样的一个执行流程就是我们Vuex中所提倡的执行方法,也是我们上方图示中所描述的执行流程。
我们知道state、mutaion、action是整个Vuex最核心的内容,在它们之外,Getter、Module也是我们必须要了解的内容。我们看下面的代码:
...
在上面的代码中,我们只贴出了关键性代码,我们把Vuex进行了模块化的区分,提供了moduleA用以描述state、getters、mutations等,具体的作用在上面的代码中有详细的注释,我们这里就不在过多叙述了。
总结在本章的内容中,我们并没有一头扎进Vuex的细节中,因为对Vuex来说,它的具体使用方式比较容易,只要我们能够理解它的本质作用,它的执行流程那么在我们使用Vuex的时候就会水到渠成。
除去我们讲到的Vuex的核心功能之外,Vuex还提供了一些其他的功能,比如plugins插件,这些内容在Vuex官网中介绍的非常清楚,我们这里就不想在进行重复介绍了。
···································
欢迎关注课程:
《入门移动端混合开发 实战京东 APP》



