can/Should 如何防止动作改变 vuex 中的状态?

How can/Should I prevent actions from mutating the state in vuex?

我们应该在突变中更新状态,这些突变可以在动作中调用。没关系。但是,看看下面的例子:

actions: {
    markMessageAsRead({ state, commit }, payload) {
      const messageId = payload.messageId
      const messages = state.messages[payload.chatId]
      const message = messages[messageId]

      message.status = 'read'  // <---- THIS ALREADY MUTATES THE STATE!
      commit('UPDATE_MESSAGE', { messageId, message }) // <---- BEFORE THIS
    },
}

在上面的示例中,在 commit(...) 行之前,由于 message.status = 'read' 行,消息已经更新。

所以,为了防止在操作中改变状态,我是否应该在更改其道具之前始终从状态中复制一个对象?有什么我错了吗?从状态获取内容并更新它的正确方法是什么?希望我解释的好。

如果您正在更新有效负载以使您的突变更具可重用性,那么单个突变的可重用性而不是更有针对性的突变(例如 SET_STATUS)并不能证明增加的复杂性在改变它之前克隆状态(看看下面的代码,它更干净简单)。

对我来说,只更新单个道具(当唯一目的是更新单个道具时)是一种更具可维护性和可扩展性的方法,可以进行更有针对性的更改,因为这避免了不必要的总是考虑只要目标 属性 存在于对象上,对存储状态所做的所有更改。

因此,在您的情况下,由于调用您的操作的唯一目的是将消息标记为已读,因此我会进行 SET_STATUS 突变,并避免在突变之外对状态进行任何其他操作。

mutations: {
    SET_STATUS(state, {messageId, chatId, status){
      state.messages[chatId][messageId].status = status
    }
}

actions: {
    markMessageAsRead({ state, commit }, payload) {
      commit('SET_STATUS', { messageId: payload.messageId, chatId: payload.chatId,  status: 'read' })
    },
}