Vuex是一个专门为vue.js应用程序开发的状态管理模式,用于集中式存储和管理应用的所有软件的状态
比如我们需要保存的用户登陆信息,购物车信息,或多个页面共享的信息等;
什么是单项数据流?
单向数据流”理念的简单示意:
![]()
State将数据映射到View,View中的Actions事件改变State数据源
单项数据流有一些弊端,当我们多个组件共享一个状态时,我们每个组件都需要去操作这个数据,这样会使得代码非常臃肿。
因此,Vuex将组件的共享状态抽离出来,以一个全局单例模式来进行管理。
Vuex基础
![]()
基本使用
1.首先,需要将vuex安装,因为是运行时依赖,所以:
npm install vuex --save
2.使用vue.use将它注册
vue.use(vuex)
3.创建store实例,vuex使用单一状态树,每个应用中都包含一个store实例
const store = new vuex.Store()
4.将store导出,并挂载到vue实例上
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
详细
五个基本属性:
const store = new vuex.Store({
state,
getters,
mutations,
actions,
modules:{
a:moduleA
}
})
1.state
const state = {
count : [],
name:'我是'
}
//state中存储着我们需要共享的数据源,我们可以通过 $store.state.name 拿到state中的name值
2.getter
getter是计算属性,比如当我们需要对一个数组进行过滤时,我们可以使用它:
filterArr:state=>{
return state.count.filter(s=>{
return s>2
})
}
//这边会传一个state进来,指向当前模块的state
然后我们可以直接使用这个函数
<h1>{{$store.getters.filterArr}}</h1>
那么,如果我们需要传一个值给getters中的函数呢?
我们可以直接返回一个函数:
filterArrFn:state=>{
return item=>{
return state.count.filter(s=>{
return s>item
})
}
}
<h1>{{$store.getters.filterArrFn(1)}}</h1>
3.mutations
当我们需要改变state源数据中的值时,我们可以在mutations中实现,视图层通过commit来提交事件类型:
this.$store.commit("addOb",ob); //addOb是我们在mutations中定义的事件类型,ob是我们要传入的参数,可以是一个对象。
addOb(state,ob){ //第一个参数还是默认传入的当前模块的state,第二个参数用于接收传入的值
state.count.push(ob);
}
//注意,在mutations中推荐写同步操作,如果在其中写异步操作,虽可以实现,但是devtools工具监测不到。
//所以对于异步操作,我们在actions中处理,然后commit给mutations
4.actions
actions用于处理异步操作,然后commit提交给mutations:
addCount(context){
//console.log(context)
setTimeout(() => {
context.commit("sss")
}, 1000);
}
这里使用计时器模拟异步操作,actions中定义的事件类型,默认会传入一个context参数,代表当前模块的上下文,在context中,我们可以拿到store中的属性
那么,可以拿到store中的属性,是不是可以直接更改state中的源数据,不使用commit提交呢?
测试的结果:
可以改变数据,但是devtools检测不到,所以说,任何需要改变state元数据的操作,都需要通过mutation。
addCount事件定义好了之后,可以通过dispatch来提交:
<button @click="dispatch">action</button>
dispatch(){
this.$store.dispatch("addCount")
}
5.modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割:
//定义了一个module模块
export default {
state:{
name:"我是张三"
},
mutations : {
show(state){
console.log( state.name);
state.name = '我是李四'
console.log( state.name);
}
},
}
//然后在modules中引入
import moduleA from "./modules/moduleA"
const store = new vuex.Store({
state,
getters,
mutations,
actions,
modules:{
a:moduleA
}
})
使用方法:
<h1>{{$store.state.a.name}}</h1>
使用commit,dispatch提交事件类型时不需要加前缀,和正常提交一样使用:
this.$store.commit("show");
所以,不要定义重复的事件名
那当事件名重复时,再提交会出现什么?
测试后发现:两个重复的事件都会执行!