什么是Vuex
用于共享、管理状态(数据)的插件
State
vuex中的“唯一数据源”
const { mapState } from 'vuex';
store = new Vuex.Strore({
state:{
num:0,
}
});
app = new Vue({
el:"#app",
store:store,
data:{
// 获取方法1: 直接获取
num:this.$store.state.num;
}
computed:{
// 获取方式2:利用映射
...mapState({
theNum:state=>state.num,
})
// 将state中的num映射到组件中,命名为theNum;可以通过直接调用theNum获取Num的值
}
})
Getter
对state中的数据,进行操作。类似于vue中的computed
const { mapGetters } from 'vuex';
store = new Vuex.Strore({
state:{
num:0,
},
getters:{
getNum:(state,getters)=>{ //第一个参数用于获取状态,第二个参数用于调用其他getters方法
return "store中的数据num为:"+ state.num;
}
}
});
app = new Vue({
el:"#app",
store:store,
data:{
// 获取方法1: 直接获取
num:this.$store.getters.getNum, // “store中的数据num为:0”
}
computed:{
// 获取方式2:利用映射
...mapGetters({
theNum:state=>state.num,
})
// 将getter中的getNum映射到组件中,命名为theNum;可以通过直接调用theNum获取字符串的值
}
})
Mutation
用于同步修改“状态”。类似于事件,需要提交事件之后,会得到一定响应。
const { mapGetters } from 'vuex';
store = new Vuex.Strore({
state:{
num:0,
},
mutations:{
increment:state=>{
state.num++;
},
incrementStep1:(state,step)=>{
state.num +=step;
}
incrementStep2:(state,payload)=>{
state.num +=payload.step;
}
}
});
app = new Vue({
el:"#app",
store:store,
methods:{
incrementHandle:state=>{
// 使用方法1:非对象提交
// 不带参数:
this.$store.commit('increment');
// 带参数1:
this.$store.commit('incrementStep1',5);
// 带参数2:
this.$store.commit({
type:'incrementStep2', //固定参数,mutation的名字
step:5, //该参数会存在payload对象中
})
},
// 使用方法2 利用mapMutations函数映射成组件中的函数
...mapMutations({
incrementNum:'increment', //可以通过this.incrementNum()来调用
})
}
})
mutation只能同步修改,即mutation中的操作,不能是异步的
store = new Vuex.Strore({
state:{
num:0,
},
mutations:{
increment:state=>{
setTimeout(()=>{
state.num++;
},1000)
}
}
});
【会出现视图修改了,但是state中的值未做修改的情况】
Action
用于异步调用mutation,达到异步修改状态的效果。类似于广播响应。
import { mapActions }from 'vuex';
store = new Vuex.Strore({
state:{
num:0,
},
mutations:{
increment:state=>{
state.num++;
},
incrementStep:(state,step)=>{
state.num += step
}
},
actions:{
incrementAsync:context=>{
setTimeout(()=>{
context.commit('increment');
})
},
incrementStepAsync:(context,step)=>{
setTimeout(()=>{
context.commit('incrementStep',step);
})
}
}
});
app = new Vue({
el:"#app",
store:store,
methods:{
incrementHandle:state=>{
// 使用方法1:非对象提交
// 不带参数:
this.$store.dispath('incrementAsync');
// 带参数1:
this.$store.dispath('incrementStepAsync',5);
// 带参数2:
this.$store.dispath({
type:'incrementStepAsync', //固定参数,mutation的名字
step:5, //该参数会存在payload对象中
})
},
// 使用方法2 利用mapMutations函数映射成组件中的函数
...mapActions({
incrementNum:'incrementAsync', //可以通过this.incrementNum()来调用
})
}
})
Module
讲store分割成多个module,便于管理与调用
const moduleA={
state(){},
getters:{},
mutations:{},
actions:{}
}
const moduleB={
state(){},
getters:{},
mutations:{},
actions:{}
}
const store = new Vuex.Store({
modules:{
a:moduleA,
b:moduleB
}
})
store.state.a //moduleA的状态
store.state.b //moduleB的状态
store.getter.a //moduleA的getter
- 在module的mutation和getter中,第一个参数state是内部的state
- 在module的getter中,第一个参数是局部state,第二个参数是其他getter方法的对象,第三个是rootState
- 在module的action中,context.state是局部状态,context.rootState是根节点状态
默认情况下,模块内部的action、mutation和getter,注册在全局命名空间
如果需要单独给模块开辟命名空间,可以使用如下选项:
namespaced:true
const store = new Vuex.Store({
modules:{
moduleA:{
namespaced:true,
state(){
count:0,
},
getters:{
gCount(){
// 调用getters['moduleA/gCount']
}
},
mutations:{
increment(){
// 调用commit('moduleA/increment')
}
},
actions:{
incrementAsync(){
// 调用dispath('moduleA/increment')
}
}
}
moduleB:{
state(){
count:0,
},
getters:{
gCount(){
// 调用getters['gCount']
}
},
mutations:{
increment(){
// 调用commit('increment')
}
},
actions:{
incrementAsync(){
// 调用dispath('incrementAsync')
}
}
}
}
})
项目结构
规则:
- 状态应集中在一个store对象中
- mutation是唯一的改变state的方法,只能是同步
- 异步都应该在action中
在大型项目中,可以将action、mutation、getter分离到单独文件
插件
什么是插件?
理解1:
- plugin在每次mutation后执行,由于mutation操作state的变化,但是不能记录变化。所以可以使用plugin来充当日志
使用
subscribe(mutation,state)
来编写插件逻辑代码
const myPlugin = (store)=>{
store.subscribe((mutation,state)=>{
// 在每次mutation之后调用
// mutation的格式为{ type , payload }
})
}
const store = new Vuex.Store({
plugins:[myPlugin]
})
严格模式
开启严格模式后,只能由mutation函数修改state,不然会抛出错误
const store = new Vuex.Store({
strict:true,
})
不要再发布环境使用严格模式,会损失性能。
表单处理
表单常常用
v-model
来绑定数据,对于严格模式下的vuex,数据的修改只能通过mutation,所以会产生矛盾
解决办法:从
v-model
的原理入手:v-model
=@input
+:value
<input type='text' :value='message' @input='updateMessage'>
const store = new Vuex.Store({
strict:true,
state:{
message:"this is a message first"
},
mutations:{
updateMessage(state,payload){
state.message = payload.newMessage;
}
}
})
const app = new Vue({
store:store,
template:`
<div>
<input type='text' :value='message' @input='updateMessage'>
<p>{{this.message}}</p>
</div>
`
computed:{
...mapState({
message : state => state.moduleA.message
})
}
methods:{
updateMessage(e){
this.$store.commit({
type:'updateMessage',
newMessage:e.target.value,
});
}
}
})