Vuex - 在 api 调用之前或之后提交状态更改?
Vuex - commit state changes before or after api calls?
我是 Vue 和 Vuex 的新手,我仍然不明白 crystal 我应该在异步事件期间什么时候提交状态更改?
Actions 是应该调用异步操作和修改器的地方。但是,在一个动作中,我应该在异步操作之前先调用 mutator(比方说 api 调用来保存数据),还是应该先调用 api 并在它的成功回调中调用将数据更改提交到状态的更改器。
谢谢。如果有人可以向我推荐有关此概念的文章,也会非常有帮助。
* 关于我的问题的更多细节 *
给定以下模型,其中一个预算可以有多个预算类别
state.budgets = {
1: {
month: 'October',
budgetCategories: {
1: {
id: 1,
name: 'Grocery',
budgeted: 350
},
2: {
id: 2,
name: 'Rent',
budgeted: 1000
},
3: {
id: 3,
name: 'Utilities',
budgeted: 150
}
},
2: {
month: 'November',
budgetCategories: {
1: {
id: 1,
name: 'Grocery',
budgeted: 350
},
2: {
id: 2,
name: 'Rent',
budgeted: 1000
},
3: {
id: 3,
name: 'Entertainment',
budgeted: 100
},
4: {
id: 4,
name: 'Tuition',
budgeted: 15000
}
}
},
...
}
}
假设我们要更新一个月的特定预算类别,如下所示:
state.budgets[target.key].budgetCategories[target.categoryId].budgeted = 200
我们有两种方法可以做到这一点:
- 在调用 api 和 mutator 之前先深度复制模型:
// mutation.js
UPDATE_BUDGET_CATEGORY(state, payload) {
state.budgets[payload.budget.id].budgetCategories[payload.budgetCategory.id] = payload.budgetCategory
}
// action.js
export const updateBudgetCategory = ({
commit,
dispatch,
getters
}, data) {
// deep copy the model
let budget = { ...getters.getBudgetById(data.budget.id)
}
const newBudget = data.budgetCategory.budgeted
const oldBudget = budget.budgetCategories[data.budgetCategory.id].budgeted
if (oldBudget !== newBudget) {
// update the model
budget.budgetCategories[data.budgetCategory.id].budgeted = newBudget
// api call to save the updated model
return api.updateBudget(budget).then(
response => {
// commit to store state
commit('UPDATE_BUDGET_CATEGORY', data)
},
error => {
// don't commit
console.log(error.message)
}
)
}
}
优点:这是正确的顺序。 store state中的数据与数据库中的数据是一致的。
缺点:每次更新对象时都必须深拷贝模型。此外,更新深度克隆模型的代码与修改器中的代码基本相同。绝对看起来是多余的而不是干的。
- 先提交数据更改,然后从状态中检索模型以将其提交到数据库:
// action.js
export const updateBudgetCategory = ({
commit,
dispatch,
getters
}, data) {
// deep copy the model
const newBudget = data.budgetCategory.budgeted
const oldBudget = getters.getBudgetById(data.budget.id).budgetCategories[data.budgetCategory.id].budgeted
if (!oldBudget !== newBudget) {
commit('UPDATE_BUDGET_CATEGORY', data)
//api call to save the updated model from the state
return api.updateBudget(getters.getBudgetById(data.budget.id))
}
}
优点:代码干净整洁。我们告诉 mutator 发生了什么,它负责更新状态。
缺点:那么api调用失败怎么办? Vuex 中有内置的 revert-commit 吗?
如果您要更新的状态取决于异步调用结果,那么显然您需要等待调用完成并提交结果。
如果与异步调用结果无关,则可以立即提交。
我是 Vue 和 Vuex 的新手,我仍然不明白 crystal 我应该在异步事件期间什么时候提交状态更改?
Actions 是应该调用异步操作和修改器的地方。但是,在一个动作中,我应该在异步操作之前先调用 mutator(比方说 api 调用来保存数据),还是应该先调用 api 并在它的成功回调中调用将数据更改提交到状态的更改器。
谢谢。如果有人可以向我推荐有关此概念的文章,也会非常有帮助。
* 关于我的问题的更多细节 *
给定以下模型,其中一个预算可以有多个预算类别
state.budgets = {
1: {
month: 'October',
budgetCategories: {
1: {
id: 1,
name: 'Grocery',
budgeted: 350
},
2: {
id: 2,
name: 'Rent',
budgeted: 1000
},
3: {
id: 3,
name: 'Utilities',
budgeted: 150
}
},
2: {
month: 'November',
budgetCategories: {
1: {
id: 1,
name: 'Grocery',
budgeted: 350
},
2: {
id: 2,
name: 'Rent',
budgeted: 1000
},
3: {
id: 3,
name: 'Entertainment',
budgeted: 100
},
4: {
id: 4,
name: 'Tuition',
budgeted: 15000
}
}
},
...
}
}
假设我们要更新一个月的特定预算类别,如下所示: state.budgets[target.key].budgetCategories[target.categoryId].budgeted = 200
我们有两种方法可以做到这一点:
- 在调用 api 和 mutator 之前先深度复制模型:
// mutation.js
UPDATE_BUDGET_CATEGORY(state, payload) {
state.budgets[payload.budget.id].budgetCategories[payload.budgetCategory.id] = payload.budgetCategory
}
// action.js
export const updateBudgetCategory = ({
commit,
dispatch,
getters
}, data) {
// deep copy the model
let budget = { ...getters.getBudgetById(data.budget.id)
}
const newBudget = data.budgetCategory.budgeted
const oldBudget = budget.budgetCategories[data.budgetCategory.id].budgeted
if (oldBudget !== newBudget) {
// update the model
budget.budgetCategories[data.budgetCategory.id].budgeted = newBudget
// api call to save the updated model
return api.updateBudget(budget).then(
response => {
// commit to store state
commit('UPDATE_BUDGET_CATEGORY', data)
},
error => {
// don't commit
console.log(error.message)
}
)
}
}
优点:这是正确的顺序。 store state中的数据与数据库中的数据是一致的。
缺点:每次更新对象时都必须深拷贝模型。此外,更新深度克隆模型的代码与修改器中的代码基本相同。绝对看起来是多余的而不是干的。
- 先提交数据更改,然后从状态中检索模型以将其提交到数据库:
// action.js
export const updateBudgetCategory = ({
commit,
dispatch,
getters
}, data) {
// deep copy the model
const newBudget = data.budgetCategory.budgeted
const oldBudget = getters.getBudgetById(data.budget.id).budgetCategories[data.budgetCategory.id].budgeted
if (!oldBudget !== newBudget) {
commit('UPDATE_BUDGET_CATEGORY', data)
//api call to save the updated model from the state
return api.updateBudget(getters.getBudgetById(data.budget.id))
}
}
优点:代码干净整洁。我们告诉 mutator 发生了什么,它负责更新状态。
缺点:那么api调用失败怎么办? Vuex 中有内置的 revert-commit 吗?
如果您要更新的状态取决于异步调用结果,那么显然您需要等待调用完成并提交结果。
如果与异步调用结果无关,则可以立即提交。