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' })
},
}
我们应该在突变中更新状态,这些突变可以在动作中调用。没关系。但是,看看下面的例子:
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' })
},
}