Vuex中的Mutations
一、Mutation状态更新
- 更改 Vuex 的
store中的状态的唯一方法是提交mutation。 - Vuex 中的
mutation非常类似于事件:每个mutation都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数:
const store = new Vuex.Store({
state: {
count: 1
},
mutations: {
increment (state) {
// 变更状态
state.count++
}
}
})
这里的
increment就是事件类型,后面跟的函数就是回调函数
- 你不能直接调用一个
mutation handler回调函数。这个选项更像是事件注册:“当触发一个类型为increment的mutation时,调用此函数。”要唤醒一个mutation handler,你需要以相应的type调用store.commit方法:
methods: {
addition() {
this.$store.commit('increment')
}
}
二、Mutation传递参数,也称作提交载荷(Payload)
- 在通过
mutation更新数据的时候, 有可能我们希望携带一些额外的参数,你可以向store.commit传入额外的参数,即mutation的 载荷(payload):
<button @click="addCount(5)">+5</button>
methods: {
addCount(count) {
this.$store.commit('incrementCount', count)
}
}
mutations: {
incrementCount(state, count) {
state.counter += count
}
}
- 但是如果参数不是一个呢?比如我们有很多参数需要传递,这个时候,我们通常会以对象的形式传递, 也就是
payload是一个对象,这个时候可以再从对象中取出相关的信息:
methods: {
addCount(count) {
this.$store.commit('incrementCount', {count: 5})
}
}
mutations: {
incrementCount(state, payload) {
state.counter += payload.count
}
}
三、Mutation提交风格
- 上面的通过
commit进行提交是一种普通的方式 - 提交
mutation的另一种方式是直接使用包含type属性的对象:
methods: {
addCount(count) {
this.$store.commit({
type: 'incrementCount',
count
})
}
}
Mutation中的处理方式是将整个commit的对象作为payload使用, 所以代码没有改变, 依然如下:
mutations: {
incrementCount(state, payload) {
state.counter += payload.count
}
}
四、Mutation响应规则
- Vuex的store中的
state是响应式的, 当state中的数据发生改变时, Vue组件会自动更新. - 这就要求我们必须遵守一些Vuex对应的规则:
- 提前在
store中初始化好所需的属性. - 当给state中的对象添加新属性时, 使用下面的方式:
- 方式一: 使用
Vue.set(obj, 'newProp', 123) - 方式二: 用新对象给旧对象重新赋值,利用对象展开运算符我们可以这样写:
- 方式一: 使用
- 提前在
state.obj = { ...state.obj, newProp: 123 }
五、Mutation常量类型
- 我们来考虑下面的问题:
- 在mutation中, 我们定义了很多事件类型(也就是其中的方法名称).
- 当我们的项目增大时, Vuex管理的状态越来越多, 需要更新状态的情况越来越多, 那么意味着Mutation中的方法越来越多.
- 方法过多, 使用者需要花费大量的经历去记住这些方法, 甚至是多个文件间来回切换, 查看方法名称, 甚至如果不是复制的时候, 可能还会出现写错的情况.
- 如何避免上述的问题呢?
- 在各种Flux实现中, 一种很常见的方案就是使用常量替代Mutation事件的类型.
- 我们可以将这些常量放在一个单独的文件中, 方便管理以及让整个app所有的事件类型一目了然.
- 具体怎么做呢?
- 我们可以创建一个文件:
mutation-types.js, 并且在其中定义我们的常量. - 定义常量时, 我们可以使用ES2015中的风格, 使用一个常量来作为函数的名称.
- 我们可以创建一个文件:
// mutation-types.js
export const INCREMENT = 'increment'
import Vuex from 'vuex'
import { INCREMENT } from './mutation-types'
const store = new Vuex.Store({
state: { ... },
mutations: {
// 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
[INCREMENT] (state) {
// mutate state
}
}
})
六、Mutation同步函数
- 通常情况下, Vuex要求我们
Mutation中的方法必须是同步方法.- 主要的原因是当我们使用devtools时, 可以devtools可以帮助我们捕捉mutation的快照.
- 但是如果是异步操作, 那么devtools将不能很好的追踪这个操作什么时候会被完成.
- 现在想象,我们正在 debug 一个 app 并且观察 devtool 中的 mutation 日志。每一条 mutation 被记录,devtools 都需要捕捉到前一状态和后一状态的快照。然而,在下面的例子中 mutation 中的异步函数中的回调让这不可能完成:因为当 mutation 触发的时候,回调函数还没有被调用,devtools不知道什么时候回调函数实际上被调用——实质上任何在回调函数中进行的状态的改变都是不可追踪的。
mutations: {
someMutation (state) {
api.callAsyncMethod(() => {
state.count++
})
}
}
本文深入解析Vuex中的Mutations概念,包括状态更新、参数传递、提交风格、响应规则及常量类型的运用,帮助读者掌握Vuex核心机制。
1510

被折叠的 条评论
为什么被折叠?



