简体   繁体   English

Vuex 突变和操作职责

[英]Vuex mutations and actions responsibilities

Except that a mutation must be synchronous whereas an action can contain asynchronous code, I find it difficult to establish some guidelines on how to correctly choose where the logic is supposed to be implemented.除了突变必须是同步的而动作可以包含异步代码之外,我发现很难就如何正确选择应该实现逻辑的位置建立一些指导方针。

The Vuex doc describes the mutations as transactions, which makes me think that each mutation must ensure as much as possible state coherence, potentially doing multiple changes in the store within the same mutation. Vuex 文档将变更描述为事务,这让我认为每个变更都必须确保尽可能多的状态一致性,可能会在同一个变更内的存储中进行多次更改。

Let's take for example the following state, storing documents that can either be loading or loaded:让我们以以下状态为例,存储可以加载或加载的文档:

const state = {
  loading: []
  loaded: []
}

const mutations = {
  setLoaded(state, doc) {
    state.loaded.push(doc)
    // Remove doc from loading:
    const index = state.loading.find(loadingDoc => doc.id === loadingDoc.id)
    if (index !== -1) {
      state.loading.splice(index, 1)
    }
  }
}

Here the mutation ensures that the doc is either in loading or loaded state, not both.这里的突变确保文档处于加载或加载状态,而不是两者。 The problem doing so is that the mutations could eventually end up having a lot of logic, which could make them more difficult to debug through the Vuex dev tools.这样做的问题是突变最终可能会包含很多逻辑,这可能会使它们更难通过 Vuex 开发工具进行调试。

Some prefer to keep the mutations as simple as possible (eg. only one state change per mutation), but then it's up to the actions (or the components in case they directly call mutations) to ensure state coherence, which could be more error-prone since, in the above example, you would need to remove the doc from loading state each time you call the “setLoaded” mutation.有些人更喜欢保持突变尽可能简单(例如,每个突变只改变一个状态),但随后由动作(或组件,如果它们直接调用突变)来确保状态一致性,这可能会导致更多错误——因为,在上面的示例中,每次调用“setLoaded”突变时,您都需要从加载状态中删除文档。

As for data validation, unluckily we have no simple way to do it in mutations since mutations cannot return anything.至于数据验证,不幸的是我们没有简单的方法可以在突变中做到这一点,因为突变不能返回任何东西。 So an action calling a mutation has no way to know that the data is invalid.因此,调用突变的操作无法知道数据无效。 Eg.:例如。:

const mutations = {
  setValue(state, intValue) {
    if (intValue < 0) {
      // error
      return
    }
    state.value = intValue;
  }
}

Thus, it seems that data validation needs to be done in actions, with mutations assuming that the data they receive are correct.因此,数据验证似乎需要在操作中完成,突变假设它们接收到的数据是正确的。

What are your thoughts about this, and more generally about actions and mutations?您对此有何看法,更一般地说是关于行动和突变的看法? Do you have guidelines on how to properly use them from your own experience?您是否有根据自己的经验正确使用它们的指南?

Data validation MUST be done in actions if it encompasses multiple mutations and/or needs to signal to the caller if the operation failed.如果数据包含多个突变和/或需要在操作失败时向调用者发出信号,则必须在操作中完成数据验证。

My rule (and this will be argued...) is to always use async CALLS (with async/await) whenever possible, even if I am calling sync methods.我的规则(这将被争论......)是尽可能始终使用异步调用(带有异步/等待),即使我正在调用同步方法。 Then my code is future proof if the sync method becomes async.如果同步方法变为异步,那么我的代码是面向未来的。 And in the case you mentioned, it also allows a return value and/or error from Vuex.在您提到的情况下,它还允许来自 Vuex 的返回值和/或错误。

let response
response = await anAsyncMethod()
response = await aSyncMethod()
response = await aVuexMutateOp()
response = await aVueActionOp()

Yes this adds a bit of processing overhead, but it is also just as clear by using async/await syntax.是的,这会增加一些处理开销,但使用 async/await 语法也同样清楚。 It streamlines the error processing as well, routing it to a catch block.它也简化了错误处理,将其路由到一个 catch 块。

Because mutations have the restriction that they MUST be synchronous AND CANNOT call other mutations AND DO NOT return a value demonstrates that the mutate should only be used in the simplest of situations.因为突变有一个限制,它们必须是同步的,不能调用其他突变,并且不返回值,这表明 mutate 应该只在最简单的情况下使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM