今天的学习围绕一张图片展开(图片引用自Vuex官方文档),当我们的项目比较大时,Vuex为我们在可以在组件外部管理状态提供了条件
一、 State
【解释】状态的意思,顾名思义,这里就是存放状态的地方,简单来说,就是存放你需要共享的某些变量的地方
【使用】当我们在state中设置了相应的变量后,我们就可以来引用它们了,之前说过,当我们安装了Vuex后,会在全局生成一个store对象,我们可以使用,我们就可以使用这个store对象来访问我们的变量,如
,couter我已经在state中添加了它的值{{$store.state.counter}}
【相关知识】 State单一状态树(Single Source of Truth)又叫做单一数据源,也就是说Vuex中建议我们在Store中存放一个Store对象的实例,这个实例就是数据源,如果数据源特别多,就不容易进行后期的维护和管理,所以最好只有一个Store实例,这就叫做单一状态树
二、 Mutations
【解释】转变、改变的意思,和Vue实例中的methods属性差不多,主要存放的是处理数据的各个方法
【使用】在Mutations中定义的各个函数都会有一个参数state,用来获取相应的数据,可以通过state调用state中存储的数据,进行相应转化,比如当我们在一个按钮中监听点击事件调用的那个函数时,函数中需要使用this.$store.commit(Mutations中的函数名);
来调用Mutations中的函数进行处理,在commit中还可以同时提交一个对象交由Mutations处理,例如
// 第一种风格
addStu(){
const info = {
id:1005,
name:'lzx',
age:20
}
//payload
this.$store.commit('addStu',info);
// 第二种风格
jianCoun(num){
this.$store.commit({
type: 'resolveNum',
num,
age:18
})
},
这里我们传了一个info对象,这个info对象就被叫做payload,负载、载荷的意思,同时我们可以这么处理(students是state中的一个数组):
addStu(state,info){
state.students.push(info);
},
值得注意的是,在Vuex中同样有像Vue中数组的有些方法一样不是响应式的,因为Vuex中store状态的更新唯一方式是提交Mutations,比如state.info['address'] = 'LiShui'
在info对象中添加属性address,值为‘LiShui’,我们应该这样Vue.set(state.info,'address','LiShui');
还有一个delete state.info.age;
也不是响应式的,应该修改为Vue.delete(state.info,'age');
总之,我们必须遵守一些规则才能做到响应式:1. 提前在store中初始化好所需的属性;2.当给state中的对象添加新的属性时使用Vue.set
或是用新对象给就对象重新赋值的方式进行
三、 Getters
【解释】获得、得到的意思,和Vue实例中的computed属性差不多,是对数据进行转化的地方
【使用】同样,在getters中定义的各个函数都有一个state参数,除此之外还有一个geter参数,可以获得自己getter下的其它函数,例如:
moreAge(state){
return state.students.filter(s=>s.age>5);
},
numAge(state,get){
return get.moreAge.length;
},
调用也很简单
<h2>{{$store.getters.moreAge}}</h2>
<h2>{{$store.getters.numAge}}</h2>
同样的调用的时候也可以传入参数例如:
{{$store.getters.whatAge(30)}}
处理如下:
whatAge(state){
return age => {
return state.students.filter(s=>s.age>age);
}
}
这种用法注意一下,和灵活,返回可以是一个函数
四、 Actions
【解释】行动、行为的意思,在这里编写我们的异步代码,由最开始的那张图片我们可以知道,当你有一些异步请求时如果我们在 Mutations中处理,我们的Devtools没办好很好的跟踪这个操作什么时候会很好的完成,所以我们在Actions中编写我们的异步代码
【使用】直接贴代码吧,一下是调用那端的代码
changeStu(){
// 1. 这种方式第二个参数可以传函数,但是如果有其他参数就不好用了
// this.$store.dispatch('changeStu', () => {
// console.log('ok');
// })
// 2.既有函数又有其他参数 但是不够优雅
// this.$store.dispatch('changeStu',{
// message:'hello actions',
// succeed(){
// console.log('已完成');
// }
// })
//3. Promise
this.$store.dispatch('changeStu','hello actions').then(res => {
console.log('里面已经完成了');
console.log(res);
})
},
以下是处理那端代码,也就是actions中的代码:
// context 上下文
changeStu(context,payload){
return new Promise((resolve,reject) => {
setTimeout(() => {
context.commit('changeStu');
console.log(payload);
resolve('11111')
}, 1000);
})
// setTimeout(()=>{
// console.log(payload);
// context.commit('changeStu');
// console.log(payload.message);
// payload.succeed();
// },1000)
}
五、 Modules
【解释】 模块的意思,Vue使用的是单一状态数,那么也意味着很多状态都会交给Vuex来管理,当应用变得非常复杂时,store对象就有可能变得相当臃肿,为了解决这个问题,Vuex允许我们将store分割成模块,而每一个模块拥有自己的state mutations actions getters
【使用】代码如下:
调用端的代码:
<h2>{{$store.state.a.name}}</h2>
<button @click="updataName">修改名字</button>
<h2>{{$store.getters.aUpdateName}}</h2>
<h2>{{$store.getters.bUpdateName}}</h2>
<h2>{{$store.getters.cUpdateName}}</h2>
<button @click="AsyncUpdataName">异步修改名字</button>
methods中的代码:
updataName(){
this.$store.commit('updateName','JYQ')
},
AsycUpdataName(){
this.$store.dispatch('AsycUpdateName');
}
module中的代码
modules:{
a: moduleA,
}
const moduleA = {
state:{
name: 'beanBag'
},
mutations:{
updateName(state,payload){
state.name = payload;
}
},
getters:{
aUpdateName(state){
return state.name + '1'
},
bUpdateName(state,getter){
return getter.aUpdateName + '2'
},
cUpdateName(state,getter,rootState){
return getter.bUpdateName + rootState.counter
}
},
actions:{
AsyncUpdateName(context){
setTimeout(() => {
context.commit('updateName','hqc');
}, 1000);
}
},
}