在Vuex中,同时拥有“动作”和“突变”的逻辑是什么?
我理解组件不能修改状态的逻辑(这看起来很聪明),但同时拥有动作和突变似乎是在编写一个函数来触发另一个函数,然后再改变状态。
“动作”和“突变”之间的区别是什么,它们是如何一起工作的,更重要的是,我很好奇Vuex开发人员为什么决定这样做?
在Vuex中,同时拥有“动作”和“突变”的逻辑是什么?
我理解组件不能修改状态的逻辑(这看起来很聪明),但同时拥有动作和突变似乎是在编写一个函数来触发另一个函数,然后再改变状态。
“动作”和“突变”之间的区别是什么,它们是如何一起工作的,更重要的是,我很好奇Vuex开发人员为什么决定这样做?
当前回答
1.从文档:
动作类似于突变,区别在于:
操作不会导致状态突变,而是导致突变。 动作可以包含任意异步操作。
action可以包含异步操作,但是突变不能。
2.我们调用突变,就能直接改变状态。我们也可以这样改变状态:
actions: {
increment (store) {
// do whatever ... then change the state
store.commit('MUTATION_NAME')
}
}
action是为处理更多其他事情而设计的,我们可以在那里做很多事情(我们可以使用异步操作),然后通过调度突变来改变状态。
其他回答
1.从文档:
动作类似于突变,区别在于:
操作不会导致状态突变,而是导致突变。 动作可以包含任意异步操作。
action可以包含异步操作,但是突变不能。
2.我们调用突变,就能直接改变状态。我们也可以这样改变状态:
actions: {
increment (store) {
// do whatever ... then change the state
store.commit('MUTATION_NAME')
}
}
action是为处理更多其他事情而设计的,我们可以在那里做很多事情(我们可以使用异步操作),然后通过调度突变来改变状态。
动作和突变之间的主要区别:
在突变中,你可以改变状态,但不能改变它的行为。 您可以在动作内部运行异步代码,但不能在突变中运行。 在动作内部,你可以访问getter,状态,突变(提交它们),动作(分派它们)等等,在突变中你只能访问状态。
问题1:Vuejs的开发者为什么决定这样做?
答:
当您的应用程序变得很大,并且有多个开发人员在这个项目上工作时,您会发现“状态管理”(特别是“全局状态”)变得越来越复杂。 Vuex方式(就像react.js中的Redux一样)提供了一种新的机制来管理状态、保持状态和“保存和跟踪”(这意味着每个修改状态的操作都可以被调试工具vue-devtools跟踪)
问题2:“action”和“mutation”有什么区别?
让我们先看看官方的解释:
Mutations: Vuex mutations are essentially events: each mutation has a name and a handler. import Vuex from 'vuex' const store = new Vuex.Store({ state: { count: 1 }, mutations: { INCREMENT (state) { // mutate state state.count++ } } }) Actions: Actions are just functions that dispatch mutations. // the simplest action function increment ({commit}) { commit('INCREMENT') } // a action with additional arguments // with ES2015 argument destructuring function incrementBy ({ dispatch }, amount) { dispatch('INCREMENT', amount) }
以下是我对上述问题的解释:
突变是改变状态的唯一方法 突变并不关心业务逻辑,它只关心“状态” 操作是业务逻辑 动作一次可以提交多个突变,它只实现业务逻辑,不关心数据更改(由突变管理)
我已经专业地使用Vuex大约3年了,以下是我认为我已经弄清楚的动作和突变之间的本质区别,如何从良好地使用它们中受益,以及如果使用不好,如何使您的生活更加困难。
The main goal of Vuex is to offer a new pattern to control the behaviour of your application: Reactivity. The idea is to offload the orchestration of the state of your application to a specialized object: a store. It conveniently supplies methods to connect your components directly to your store data to be used at their own convenience. This allows your components to focus on their job: defining a template, style, and basic component behaviour to present to your user. Meanwhile, the store handles the heavy data load.
That is not the only advantage of this pattern though. The fact that stores are a single source of data for the entirety of your application offers a great potential for re-usability of this data across many components. This isn't the first pattern that attempts to address this issue of cross-component communication, but where it shines is that it forces you to implement a very safe behaviour in your application by basically forbidding your components to modify the state of this shared data, and force it instead to use "public endpoints" to ask for change.
基本思想是这样的:
The store has an internal state, which should never be directly accessed by components (mapState is effectively banned) The store has mutations, which are synchronous modifications to the internal state. A mutation's only job is to modify the state. They should only be called from an action. They should be named to describe things that happened to the state (ORDER_CANCELED, ORDER_CREATED). Keep them short and sweet. You can step through them by using the Vue Devtools browser extension (it's great for debugging too!) The store also has actions, which should be async or return a promise. They are the actions that your components will call when they want to modify the state of the application. They should be named with business oriented actions (verbs, i.e. cancelOrder, createOrder). This is where you validate and send your requests. Each action may call different commits at different steps if it is required to change the state. Finally, the store has getters, which are what you use to expose your state to your components. Expect them to be heavily used across many components as your application expands. Vuex caches getters heavily to avoid useless computation cycles (as long as you don't add parameters to your getter - try not to use parameters) so don't hesitate to use them extensively. Just make sure you give names that describe as closely as possible what state the application currently is in.
话虽如此,当我们开始以这种方式设计应用程序时,魔法就开始了。例如:
We have a component that offers a list of orders to the user with the possibility to delete those orders The component has mapped a store getter (deletableOrders), which is an array of objects with ids The component has a button on each row of orders, and its click is mapped to a store action (deleteOrder) which passes the order object to it (which, we will remember, comes from the store's list itself) The store deleteOrder action does the following: it validates the deletion it stores the order to delete temporarily it commits the ORDER_DELETED mutation with the order it sends the API call to actually delete the order (yes, AFTER modifying the state!) it waits for the call to end (the state is already updated) and on failure, we call the ORDER_DELETE_FAILED mutation with the order we kept earlier. The ORDER_DELETED mutation will simply remove the given order from the list of deletable orders (which will update the getter) The ORDER_DELETE_FAILED mutation simply puts it back, and modifies the state to notify of the error (another component, error-notification, would be tracking that state to know when to display itself)
最后,我们的用户体验被认为是“反应性的”。从用户的角度来看,该项目已被立即删除。大多数时候,我们希望端点正常工作,所以这很完美。当它失败时,我们仍然可以控制应用程序的反应,因为我们已经成功地将前端应用程序的状态与实际数据分离。
请注意,你并不总是需要商店。如果你发现你正在写这样的存储:
export default {
state: {
orders: []
},
mutations: {
ADD_ORDER (state, order) {
state.orders.push(order)
},
DELETE_ORDER (state, orderToDelete) {
state.orders = state.orders.filter(order => order.id !== orderToDelete.id)
}
},
actions: {
addOrder ({commit}, order) {
commit('ADD_ORDER', order)
},
deleteOrder ({commit}, order) {
commit('DELETE_ORDER', order)
}
},
getters: {
orders: state => state.orders
}
}
在我看来,您只是将存储用作数据存储,并且可能错过了它的反应性方面,因为没有让它也控制应用程序响应的变量。基本上,您可以也应该将组件中编写的一些代码卸载到存储中。
突变是同步的,而操作可以是异步的。
换句话说:如果您的操作是同步的,则不需要操作,否则就实现它们。