在Vuex中,同时拥有“动作”和“突变”的逻辑是什么?
我理解组件不能修改状态的逻辑(这看起来很聪明),但同时拥有动作和突变似乎是在编写一个函数来触发另一个函数,然后再改变状态。
“动作”和“突变”之间的区别是什么,它们是如何一起工作的,更重要的是,我很好奇Vuex开发人员为什么决定这样做?
在Vuex中,同时拥有“动作”和“突变”的逻辑是什么?
我理解组件不能修改状态的逻辑(这看起来很聪明),但同时拥有动作和突变似乎是在编写一个函数来触发另一个函数,然后再改变状态。
“动作”和“突变”之间的区别是什么,它们是如何一起工作的,更重要的是,我很好奇Vuex开发人员为什么决定这样做?
当前回答
这似乎没有必要有一个额外的操作层来调用突变,例如:
const actions = {
logout: ({ commit }) => {
commit("setToken", null);
}
};
const mutations = {
setToken: (state, token) => {
state.token = token;
}
};
因此,如果调用actions调用注销,为什么不调用突变本身呢?
动作的整个思想是从一个动作内部调用多个突变,或者发出Ajax请求或任何你能想到的异步逻辑。
我们最终可能会有发出多个网络请求的动作,并最终调用许多不同的突变。
因此,我们尝试将尽可能多的复杂性从我们的Vuex.Store()中添加到我们的动作中,这使得我们的突变、状态和getter更干净、更直接,并与使Vue和React等库流行的模块化保持一致。
其他回答
根据文件
动作类似于突变,区别在于:
操作不会导致状态突变,而是导致突变。 动作可以包含任意异步操作。
考虑下面的代码片段。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++ //Mutating the state. Must be synchronous
}
},
actions: {
increment (context) {
context.commit('increment') //Committing the mutations. Can be asynchronous.
}
}
})
动作处理程序(增量)接收一个上下文对象,该对象公开相同的 方法/属性,以便您可以调用 commit来提交一个突变,或者访问状态和getter 通过上下文。State和context.getter
免责声明-我只是刚刚开始使用vuejs,所以这只是我推断的设计意图。
时间机器调试使用状态的快照,并显示动作和变化的时间轴。理论上,我们可以在记录状态设置器和获取器的同时进行操作,以同步地描述突变。但之后:
We would have impure inputs (async results) which caused the setters and getters. This would be hard to follow logically and different async setters and getters may surprisingly interact. That can still happen with mutations transactions but then we can say the transaction needs to be improved as opposed to it being a race condition in the actions. Anonymous mutations inside an action could more easily resurface these kinds of bugs because async programming is fragile and difficult. The transaction log would be hard to read because there would be no name for the state changes. It would be much more code-like and less English, missing the logical groupings of mutations. It might be trickier and less performant to instrument recording any mutation on a data object, as opposed to now where there are synchronously defined diff points - before and after mutation function call. I'm not sure how big of a problem that is.
将下面的事务日志与命名的突变进行比较。
Action: FetchNewsStories
Mutation: SetFetchingNewsStories
Action: FetchNewsStories [continuation]
Mutation: DoneFetchingNewsStories([...])
使用没有命名突变的事务日志:
Action: FetchNewsStories
Mutation: state.isFetching = true;
Action: FetchNewsStories [continuation]
Mutation: state.isFetching = false;
Mutation: state.listOfStories = [...]
我希望您能从这个例子中推断出动作中的异步和匿名突变可能增加的复杂性。
https://vuex.vuejs.org/en/mutations.html
Now imagine we are debugging the app and looking at the devtool's mutation logs. For every mutation logged, the devtool will need to capture a "before" and "after" snapshots of the state. However, the asynchronous callback inside the example mutation above makes that impossible: the callback is not called yet when the mutation is committed, and there's no way for the devtool to know when the callback will actually be called - any state mutation performed in the callback is essentially un-trackable!
这似乎没有必要有一个额外的操作层来调用突变,例如:
const actions = {
logout: ({ commit }) => {
commit("setToken", null);
}
};
const mutations = {
setToken: (state, token) => {
state.token = token;
}
};
因此,如果调用actions调用注销,为什么不调用突变本身呢?
动作的整个思想是从一个动作内部调用多个突变,或者发出Ajax请求或任何你能想到的异步逻辑。
我们最终可能会有发出多个网络请求的动作,并最终调用许多不同的突变。
因此,我们尝试将尽可能多的复杂性从我们的Vuex.Store()中添加到我们的动作中,这使得我们的突变、状态和getter更干净、更直接,并与使Vue和React等库流行的模块化保持一致。
基因突变:
Can update the state. (Having the Authorization to change the state).
行动:
Actions are used to tell "which mutation should be triggered"
用Redux的方式
突变是减速器 行动就是行动
为什么都是??
当应用程序增长时,代码和行数将会增加,这时你必须在Actions中处理逻辑,而不是在突变中,因为突变是改变状态的唯一权威,它应该尽可能干净。
因为没有突变就没有状态!提交时——执行以可预见的方式改变状态的一段逻辑。突变是设置或改变状态的唯一方法(所以没有直接的变化!),而且它们必须是同步的。这个解决方案驱动了一个非常重要的功能:突变将登录到devtools。这为您提供了良好的可读性和可预测性!
还有一件事——行动。正如我们所说的,行为会导致突变。所以它们不会改变存储,也不需要这些是同步的。但是,他们可以管理一个额外的异步逻辑!