Vue 凭借着自身简洁,轻量,快速等特点,Vue伊然成为最火的前端MVVM开发框架,越来越多的项目开始采用Vue作为前端框架,作为Vue生态中最重要的一环,Vuex逐渐被大家认识。
在正式介绍Vuex之前,数据管理模式的前世今生是很有必要说一下的。
在我们开发的时候,一定会分解出很多组件进行开发,各个组件之间在逻辑上多多少少都是有关系的。那么组件之间的“通信”,就需要解决了。以前我们用$emit,$on,$off
事件广播来实现,但随着事件越来越复杂,越来越不可预料,导致越来越难调试,越来越难追踪错误。在这种情况下,我们当然希望应用的各个部分都易维护、可扩展、好调试、能预测。在这种情况下,数据管理模式就应运而生。
如上图, 是一个最简单的组件关系,b是a的子组件,c是b的子组件,我们在c组件中想要拿到a组件中的数据,可以通过父子通信,先由a传给b,再由b传给c。但是如果组件树变得复杂,我们想拿到c的爷爷辈的数据,或者爷爷的爷爷的数据呢,那么父子结构就不怎么实用了,所以我们就需要引入数据管理模式。
上图所示是一个最简单的数据管理模式,所有的数据统一的交给全局store来管理,a组件和c组件现在直接修改store中的数据,并且通过mapState从store中获取自己需要的数据到自己组件中,完全不需要b组件,做到完全解耦。
随着数据管理的进一步发展和演变,单向数据流随之出现,Vuex就可以说是单向数据流的最佳实践者。
Vuex是什么?
Vuex是专为Vue.js应用程序开发的状态管理模式。这是官方给的说法。
这个状态我们可以理解为在data中的属性,需要共享给其他组件使用的部分。
也就是说,我们需要共享的data,使用Vuex进行统一集中式管理,跟秦始皇的中央集权一个道理,把公共的部分集中起来,统一管理。
Vuex基本思想就是单向数据流。它集中存储管理应用的所有组件的状态,并且以相应的规则保证状态以一种可预测的方式发生变化,如下图所示:
Vuex中,有默认的五种基本的对象:
- state:存储状态 (变量)
- getters:对数据获取之前的再次编译,可以理解为state的计算属性。我们在组件中使用
$store.getters.fun()
- mutations:修改状态,同步。在组件中使用
$store.commit
,和我们在组件中自定义事件差不多类似。 - actions:异步操作。在组建中使用时
$store.dispath('')
- modules:store的子模块,为了分发大型项目,方便状态管理而使用的,用法跟上面的一样,
下面我们正式开始,一步一步使用Vuex
- 首先创建一个Vue-cli项目,在创建项目的时候记得勾选Vuex
npm run serve
运行项目- 当我们引入并配置好后,就可以在store文件夹下的index.js中尽情使用Vuex了
首先我先在store文件夹下的index.js文件中定义一个count属性,那么我们在任意一个组件中就可以使用定义好的count属性了。
这里我们在hellowWorld中使用一下,先删掉helloworld.vue中不用的标签。
export default new Vuex.Store({
state: {
count:0
},
mutations: {
},
actions: {
},
modules: {
}
})
<template>
<div class="hello">
<h3>{{$store.state.count}}</h3>
</div>
</template>
打开我们刚运行起来的项目浏览器,列位,你已经成功了!
打开vue开发工具中我们可以看到我们定义的变量count
到这里我们已经成功了一小半了,现在我们已经使用了Vuex中的state,哪我们应该如何操作这个值呢?
我们继续操作index.js文件,在文件中定义mutations对象,对象中放入两个方法,增加和减少,病设置一个参数n,默认值为0
xport default new Vuex.Store({
state: {
count:0
},
mutations: { // mutations 里面放置的是我们操作state对象属性的方法
mutationsAddCount(state, n = 0) {
return (state.count += n)
},
mutationsReduceCount(state, n = 0) {
return (state.count -= n)
}
},
actions: {
},
modules: {
}
})
然后我们在helloWorld.vue中,使用这个方法
<template>
<div class="hello">
<h3>{{$store.state.count}}</h3>
<div>
<button @click="handleAddClick(10)">增加</button>
<button @click="handleReduceClick(10)">减少</button>
</div>
</div>
</template>
methods: {
handleAddClick(n){
this.$store.commit('mutationsAddCount',n);
},
handleReduceClick(n){
this.$store.commit('mutationsReduceCount',n);
}
}
我们进入浏览器看一下效果,当我们触发事件时,都可以在vue开发工具中看到我们触发mutations方法,以及参数
接下来就是actions,actions是异步操作
这里我在两个方法中使用了两个不同的参数,一个是context,它是一个和store对象具有相同对象属性的参数。在第二个函数中,我是直接使用了这个对象的commit的方法。
actions: {
actionsAddCount(context, n = 0) {
console.log(context)
return context.commit('mutationsAddCount', n)
},
actionsReduceCount({ commit }, n = 0) {
return commit('mutationsReduceCount', n)
}
},
在helloWorld.vue中
在methods中,增加两个方法,使用dispath来触发
<div>异步操作</div>
<div>
<button @click="handleActionsAdd(10)">异步增加</button>
<button @click="handleActionsReduce(10)">异步减少</button>
</div>
handleActionsAdd(n){
this.$store.dispatch('actionsAddCount',n)
},
handleActionsReduce(n){
this.$store.dispatch('actionsReduceCount',n)
}
最后是getters
我们一般使用getters来获取我们的state,嗯…它算是state的一个计算属性
getters:{
getterCount(state, n = 0) {
return (state.count += n)
}
}
<h4>{{count}}</h4>
getters = {
getterCount(state) {
return (state.count += 10)
}
}
getters算是非常简单的了。
如果全都看懂了,vuex你已经没有压力了。
最后,如果大家发现什么问题,或者错误的地方,欢迎留言交流。
送给大家一句话:如果你的才华还实现不了你的野心,那就静下心来,埋头苦干。
疫情当前,逆战而上!