🤗 OK!首先恭喜你看到了这里,前面我们实现了从盘古开天辟地开始......咳咳,其实我们从初始化vue项目,到安装vuex插件,并且通过配置,我们成功访问到了store里面的state的值,之后我们发现某些场景仅仅使用这些 " 初始值 " 无法满足,所以我们学习了Getter,我们可以 " 修饰读 " 啦!很棒,接下来我来介绍一下怎么修改state里面的值。🤪提前剧透下,这个store仓库很奇怪呢,你可以随便拿,但是你不能随便放,你想放,就得登记~
-
😏 我们先看一下vuex官方的使用周期图,我们目前在绿色的地方,我们想修改紫色的地方,紫色地方的上一级就只有Mutations,所以,但凡我们想修改state,就只能走commit Mutations,别无他法。其实图中是有一些不妥的,为什么这么说,我在下面这张图做了补充。
image.png
-
🤓 其实想走到Mutations这一步,并不是像官方图那样,只有通过在Actions进行commit;其实也可以直接在vue组件里直接commit到Mutations。Actions存在的意义就是为了封装异步方法而已,如果你在改变state里面的值的时候没有异步操作,那你应该直接在组件处使用commit到Mutations,而不是非得通过Actions去commit到Mutations。
image.png
-
😬 把问题讲清楚之后,我们准备完成一个效果,我们先输出state中的num的默认值(0),然后我们在vue组件里通过commit Mutations改变state中的num的默认值(0)为我们想修改的值,然后再输出出来,这样就可以简单练习怎么使用Mutations了。不说废话,上代码。
-
- 修改store/index.js
const store = new Vuex.Store({ state:{ loading: false, todoList : [ {id:1,name:'11'}, {id:2,name:'22'}, {id:3,name:'33'}, ], num: 0, <----- 设置一个num计数器 }, mutations:{ <----- 增加nutations属性 setNumIs5(state){ <----- 增加一个mutations的方法,方法的作用是让num从0变成5,state是必须默认参数 state.num = 5 } }, }
- 修改App.vue
image.pngmounted() { console.log('旧值--'+this.$store.state.num); this.$store.commit('setNumIs5') console.log('新值--'+this.$store.state.num); }
-
🤡 以上是简单实现mutations的方法,是没有传参的,如果我们想传不固定的参数怎么办?我们想在不同的页面让num等于不同的值,怎么办,接下来教你解决。
- 修改store/index.js
const store = new Vuex.Store({ state:{ loading: false, todoList : [ {id:1,name:'11'}, {id:2,name:'22'}, {id:3,name:'33'}, ], num: 0, }, mutations:{ setNumIs5(state){ state.num = 5 }, setNumIsWhat(state,payload){ <------ 增加一个带参数的mutations方法,官方建议payload为一个对象,这样看起来美观。 state.num = payload.num } }, })
- 修改App.vue
mounted() { console.log('旧值--'+this.$store.state.num); this.$store.commit('setNumIsWhat',{ num:3 }) console.log('新值--'+this.$store.state.num); }
- 😵 疑问?你可能会问,为什么vuex更改了写法,为什么不是this.$store.mutations.setNumIs5这样写呢,而是要使用commit的方式?
官方回答:Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。你不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 setNumIs5 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法
- 😱 mutations必须是同步函数
一条重要的原则就是要记住mutation 必须是同步函数。为什么?请参考下面的例子:
现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在上面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools 不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。mutations: { someMutation (state) { api.callAsyncMethod(() => { <----- 在mutation中使用了异步方法 state.count++ }) } }
- 对于上面的解释,多读几遍,你应该就理解了。
- 🤖 官方建议:在组件中使用
mapMutations
以代替this.$store.commit('XXX')
。import {mapState,mapGetters,mapMutations} from 'vuex' export default { name: 'App', computed:{ getTodoList(){ return this.$store.state.todoList }, ...mapState({ aliasName:'loading' }), ...mapGetters({ aliasName:'getItemById' }), }, mounted() { console.log('旧值--'+this.$store.state.num); this.setNumIsWhat({num:999}) console.log('新值--'+this.$store.state.num); }, methods:{ <----- 注意,mapMutations是解构到methods里面的,而不是计算属性了。 ...mapMutations([ 'setNumIsWhat' ]) } }
- 当然你也可以给它叫别名,取外号,就像这样
methods:{ ...mapMutations({ setNumIsWhatAlias:'setNumIsWhat' }) }
🤔 OK,关于Mutation的介绍大致就是这样,你学完应该懂得了修改state的路径不止有
vue components -> actions -> mutations -> state
一条,还有vue components -> mutations -> state
这一条,用哪个就取决你是不是在修改state的时候使用了异步方法;另外你也掌握了在定义mutations方法的时候有无参数;并且听取了官方建议,使用mapMutations解构到你的组件内部的methods里,这样你就可以很简单的使用mutations方法啦!OK,本节你也简单了解了Actions,它存在的意义就是封装异步方法嘛,所以,我们马上开始下一节,看看使用Actions的时候应该注意什么!come on baby!🤪
网友评论