Vuex入门简单示例(四)
前言
我想写一系列关于Vuex的入门文章,我是看着vuex官网文档,结合自己从零搭建的vue项目来实践vuex的知识。
Vuex入门系列:
-
Vuex入门简单示例(四)
- Vuex入门简单示例(五)
本文涉及知识点:
- vuex之mutation
- vuex之mutation提交载荷(传参)
- vuex之mapMutations
vuex官方文档对mutations的描述
更改vuex的store中的状态的唯一方法是提交mutation。
你不能直接调用一个mutation handler。这个选项更像是事件注册。要唤醒一个mutation handler,你需要以相应的type调用store.commit方法
看之前文章中的示例代码,
src/components/Login.vue
// 修改isLogin状态 this.$store.commit('changeLogin', true) // 修改username状态 this.$store.commit('changeUsername', this.username) // 修改password状态 this.$store.commit('changePassword', this.password)
提交载荷
你可以向store.commit传入额外的参数,即mutation的载荷.
这里做一个用到mutation的小栗子
在store.js的state里添加一个count状态
src/store.js
state: { // ... count: 0 },
mutations里面添加2个操作count的方法,一个用来增加,一个用来重置
src/store.js
mutations: { // ... addCount(state, n) { state.count += n }, resetCount(state, data) { state.count = data; } }
回到Home.vue使用count
在计算属性的mapState里添加count
computed: { // ... ...mapState({ isLogin: state => state.isLogin, username: state => state.username, password: state => state.password, count: state => state.count }), // ... },
在methods里添加两个方法唤醒mutations
methods: { add () { this.$store.commit('addCount', 1) }, reset () { this.$store.commit('resetCount', 0) } }
最后在template里添加count相关内容
<hr> <div> <h3>mutation载荷</h3> <span>{{count}}</span> | <button @click="add">+1</button> | <button @click="reset">重置</button> </div>
两个按钮分别调用add和reset事件
运行测试一下
使用对象形式的载荷也能实现这种效果
很多时候,尤其是当数据比较复杂,使用对象形式的载荷会更好。
修改store.js mutations addCount和resetCount事件
src/store.js
addCount(state, payload) { state.count += payload.n }, resetCount(state, payload) { state.count = payload.data; }
修改Home.vue methods add和reset方法
src/components/Home.vue
add () { this.$store.commit('addCount', { n: 1 }) }, reset () { this.$store.commit('resetCount', { data: 0 }) }
效果一样。多学会一种写法总是好的。
对象风格的mutation
提交mutation的另一种方式是直接使用包含type属性的对象
结合本例,修改Home.vue
methods: { add () { this.$store.commit({ type: 'addCount', n: 1 }) }, reset () { this.$store.commit({ type: 'resetCount', data: 0 }) } }
效果一样
Mutation需遵守Vue的相应规则
以下摘自vuex官网
既然Vuex的store中的状态是响应式的,那么当我们变更状态时,监视状态的Vue组件也会自动更新。这也意味着Vuex中的mutation页需要与使用Vue一样遵守一些注意事项
- 最好提前在你的store中初始化好所需属性
- 当需要在对象上添加新属性时,你应该
- 使用Vue.set(obj, 'newProp', 123),或者
- 以新对象替换老对象。例如,
state.obj = { ...state.obj, newProp: 123 }
Mutation必须是同步函数
这个没有可以测试的接口,所以跳过吧。
在组件中提交Mutation
你可以在组件中使用this.$store.commit('xxx')提交mutation
mapMutations辅助函数
现在我们把示例修改一下,尽量用上mapMutations辅助函数
store.js不用动
在Home.vue导入mapMutations
import { mapState, mapGetters, mapMutations } from 'vuex'
在methods里面用对象展开运算符添加...mapMutations,先说第一种方式
methods: { ...mapMutations(['addCount', 'resetCount']) }
这里,如果是不带参数的mutation,可以直接调用,this.addCount,this.resetCount.
如果是带参数的,则另外写一个方法,来调用this.addCount(arg)
src/components/Home.vue
methods: { ...mapMutations(['addCount', 'resetCount']), add () { this.addCount({n: 1}) }, reset () { this.resetCount({data: 0}) } }
注意这个例子里的n和data,这两个名称是和store.js里面写的对应的。
src/store.js
addCount(state, payload) { state.count += payload.n }, resetCount(state, payload) { state.count = payload.data }
预览一下,效果一致。
第二种写法,mapMutations里面放一个对象
src/components/Home.vue
methods: { ...mapMutations({ theAdd: 'addCount', theReset: 'resetCount' }), add () { this.theAdd({n: 1}) }, reset () { this.theReset({data: 0}) } }
效果一致
参考文档:Vuex官方中文文档