2024-10-01 09:00:04

Vuex行动vs突变

在Vuex中,同时拥有“动作”和“突变”的逻辑是什么?

我理解组件不能修改状态的逻辑(这看起来很聪明),但同时拥有动作和突变似乎是在编写一个函数来触发另一个函数,然后再改变状态。

“动作”和“突变”之间的区别是什么,它们是如何一起工作的,更重要的是,我很好奇Vuex开发人员为什么决定这样做?


当前回答

1.从文档:

动作类似于突变,区别在于:

操作不会导致状态突变,而是导致突变。 动作可以包含任意异步操作。

action可以包含异步操作,但是突变不能。

2.我们调用突变,就能直接改变状态。我们也可以这样改变状态:

actions: {
  increment (store) {
    // do whatever ... then change the state
    store.commit('MUTATION_NAME')
  }
}

action是为处理更多其他事情而设计的,我们可以在那里做很多事情(我们可以使用异步操作),然后通过调度突变来改变状态。

其他回答

我认为TLDR的答案是,突变意味着同步/事务性的。因此,如果您需要运行Ajax调用,或执行任何其他异步代码,则需要在Action中执行该操作,然后提交一个突变,以设置新状态。

免责声明-我只是刚刚开始使用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!

1.从文档:

动作类似于突变,区别在于:

操作不会导致状态突变,而是导致突变。 动作可以包含任意异步操作。

action可以包含异步操作,但是突变不能。

2.我们调用突变,就能直接改变状态。我们也可以这样改变状态:

actions: {
  increment (store) {
    // do whatever ... then change the state
    store.commit('MUTATION_NAME')
  }
}

action是为处理更多其他事情而设计的,我们可以在那里做很多事情(我们可以使用异步操作),然后通过调度突变来改变状态。

突变是同步的,而操作可以是异步的。

换句话说:如果您的操作是同步的,则不需要操作,否则就实现它们。

根据文件

动作类似于突变,区别在于:

操作不会导致状态突变,而是导致突变。 动作可以包含任意异步操作。

考虑下面的代码片段。

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