Note: this proposal has been heavily revised based on feedback so some of the comments below may be out of context.
1. Terms naming change for better semantics
Dispatching a mutation never sounded right. Dispatch should be indicating the intention for something to happen. For mutations, we want a verb that indicates the state change is happening as soon as you call it.
store.dispatch is now store.commit.store.dispatch will be used for firing actions instead. (see next section)The new naming better conveys the semantics behind the two methods:
There has been common requests on shipping actions with the store, or inside modules. Previously, the reason for not putting actions in the store/modules was mainly how do we access them. Actions defined inside the store means we need access to the store - again the singleton problem, which is now a non-issue.
Now since they are just functions, we may expose them as store.actions and call them directly. In fact this was the API of Vuex 0.4.x:
store.xxx // reserved for Store class methods/properties
store.actions.xxx // this seems ok
A problem is when actions are defined inside modules, what if multiple modules define actions of the same name? Also, sometimes we may want to call an action that affect multiple stores, just like mutations.
It seems actions are also more like event listeners. Instead of calling them directly as functions, we now use store.dispatch to trigger them:
const store = new Vuex.Store({
actions: {
doSomething: ({ commit }) => {
commit('some-mutation')
}
}
})
store.dispatch('doSomething')
This way, you can dispatch actions in multiple modules with a single call, just like mutations. It's also more explicit that you are firing off some side-effects in your store, instead of just calling a random function.
You can now define getters in the store / modules too. Similar to module mutations, module getters receive the sub state tree:
const store = new Vuex.Store({
state: {
count: 0
},
getters: {
hasAny: state => state.count > 0
}
})
// access the getter
store.getters.hasAny // -> false
Now that we are putting actions inside modules and calling them via dispatch, we somehow lose out on the composability of actions, because they are no longer just functions you can call. Here's how we can make them composable again:
store.dispatch will return that Promise if there is only a single handler called. If multiple action handlers are matched, it will return a Promise that resolves when all Promises returned by those handlers are resolved.``` js
const store = new Vuex.Store({
actions: {
doSomething: ({ commit }, payload) => {
return callPromiseAPI(payload).then(res => {
commit('some-mutation', { res })
})
}
}
})
store.dispatch('doSomething', { id: 1 }).then(() => {
// action done
})
```
async/await, we can have very clean composition between async actions:``` js
const store = new Vuex.Store({
actions: {
one: async ({ commit }, payload) => {
const res = await callPromiseAPI(payload)
commit('some-mutation', { res })
},
two: async ({ dispatch, commit }) => {
await dispatch('one')
commit('done')
}
}
})
store.dispatch('two') // fires off complicated async flow
```
The convention of returning Promises also allows Vuex to:
The design of Vuex 0.6~1.0 had a somewhat annoying design constraint: avoid directly accessing stores inside components. The store is injected at the root component, and implicitly used via the vuex: { getters, actions } options. This was in preparation for Vue 2.0 SSR (server-side rendering), because in common SSR setups (directly requiring the component in Node.js and render it), dependence on a global singleton will cause that singleton to be shared across multiple requests, thus making it possible for a request to pollute the state of the next one.
However, with the new bundleRenderer strategy implemented in Vue 2.0.0-alpha.7, this is no longer an issue. The application bundle will be run in a new context for each request, making it unnecessary to structure your app without singletons just for the sake SSR. This also means it's totally fine to just import store from './store', use plain computed properties to return store.state.xxx, or calling store.dispatch() in plain methods.
This opens up path to simplifying the component binding usage, since theoretically you don't need any binding at all. Currently, the vuex options feels a bit clumsy and indirect.
In Vuex 2.0, the vuex option will be deprecated in favor of just computed properties and methods. You are free to structure your Vuex store usage the way you prefer. However, we will be keeping the injection for this.$store so that you can do this:
export default {
computed: {
a () {
return this.$store.getters.a
}
},
methods: {
b (...args) {
this.$store.dispatch('b', …args)
}
}
}
The above alleviates the need to import the store everywhere. But it can get verbose when you have many getters and actions in the same component. Therefore we provide two helpers, mapGetters and mapActions:
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters(['a', 'b', 'c']),
methods: mapActions(['d', 'e', 'f'])
}
So in the component, this.a maps to this.$store.getters.a, and this.d(...args) maps to this.$store.dispatch('d', ...args).
If you want to map a getter/action to a different local name, use an object instead:
import { mapGetters, mapActions } from 'vuex'
export default {
computed: mapGetters({
myComputed: 'a' // map this.myComputed to store.getters.a
}),
methods: mapActions({
myMethod: 'b' // map this.myMethod() to store.dispatch('b')
})
}
Finally, you can easily compose them with local computed properties and methods using Object spread operator:
import { mapGetters, mapActions } from 'vuex'
export default {
computed: {
localComputed () { … },
...mapGetters(['a', 'b', 'c', 'd'])
},
methods: {
localMethod () { … },
...mapActions(['b'])
}
}
1.0 contains small breaking changes but should be a very easy upgrade for existing 0.6~0.8 users. It will be maintained as a stable release in parallel to 2.0.
My thoughts are on the order of params inside actions.
I mean:
const store = new Vuex.Store({
actions: {
doSomething(state, payload, dispatch) {
dispatch('some-mutation', payload)
}
}
})
...could be the in the inverse order:
const store = new Vuex.Store({
actions: {
doSomething(dispatch, payload) {
dispatch('some-mutation', payload)
}
}
})
Because, inside an action you always use dispatch, then, if there is a payload, you use it.
@NicolasParada definitely, the argument orders are not set in stone - I actually was thinking about it too.
how about dynamic modules injection?
like store start with a basic set of modules then user can fetch and inject new ones.
and presumably delete them when no more needed.
This opens up path to further simplifying the component binding usage. Currently I'm interested to hear thoughts on the current binding (aka vuex: { getters, actions }).
This might have been discussed at some point, but is the vuex key necessary? I'd prefer to declare getters and actions on the top level of my component.
Kind of wish there was some way to make getters and actions play nicely with props (from a syntax point of view, having to declare getters and computed props for one thing feels like a hassle sometimes), but don't have any ideas myself.
store.dispatch('counter:incrementAsync')
I'm not sure about namespacing actions. Wouldn't that restrict you from using modules if you want a single action that can trigger multiple mutations?
Mainly, I agree with all the concepts and ideas brought in by this design. It will certainly help further simplify Vuex.
This opens up path to further simplifying the component binding usage. Currently I'm interested to hear thoughts on the current binding (aka vuex: { getters, actions }).
The vuex property key, in the current architecture is kind of necessary. For 2.0 I would consider it very unnecessary:
computed -> computedPropertyActions and mutations are now together "events". The difference being that
- mutations are synchronous and can mutate the state
- actions can be async, cannot directly mutate the state (but can trigger mutations and other actions)
I would replace store.dispatch with equivalent store.action and store.mutate.
dispatch becomes something additional to digest that does not fit in with what is learnt through Flux. mutate and action fits nicely into the concepts learnt from Flux.In agreement with @NicolasParada, this makes simple actions easier to create.
I agree with @blake-newman that store.action and store.mutate is better than store.dispatch.
I would also add that is more readable because we can immediately understand what happening on the store.
Interesting, quite a step away from Redux.
Redux community tried to bundle action creators with reducers, but I believe Dan is against it (1, 2). According to him, it kills the essence of flux: action objects and reducers are separated, any reducer can respond to any action object. That said, bundled modules are optional, so you can use then when they fit and fall back to idiomatic Redux when they don't.
To be honest, I don't like the idea of dispatching actions and mutations through a single method. I think that everything that is dispatched should be recorded by the devtools. But actions should not be recorded because of side effects. In Redux you can dispatch anything, and "non-idiomatic" chunks are processed by middleware. But it's quite confusing, I'd rather have separate methods (mutate and act?)
Onto suggestions.
With dispatch now performing prefixing (and thus being unable to affect parent modules), how about making actions take a module, which has it's local versions of module.dispatch and module.state? This would simplify action signature from state, payload, dispatch, [done] to module, payload, [done]. We can even keep calling it store, but it will change semantincs to be a "local store, aka module".
UPDATE: Added references to Dan's words:
@simplesmiler I think there is a real need for actions defined alongside mutations, which doesn't prevent a higher-up action from dispatching multiple namespaced mutations.
I like the arguments simplification - it also keeps it closer to the current API, so the signature remains almost he same:
(state, payload) => void({ dispatch, state }, payload, [done]) => any@sleewoo that's something I've been thinking too! It could also be used for hot-reloading a module. Maybe something like store.module(id, { ... }).
@sebastiandedeyne I also feel the nesting is a bit awkward. In 2.0 we may get rid of the options all together, so you can just do this.$store.dispatch() in normal methods + return this.$store.state.xxx in computed properties.
If you want a single action to trigger multiple mutations, you just need to be more explicit:
dispatch('moduleA:increment')
dispatch('moduleB:increment')
I think this actually makes the data flow clearer: you know you are triggering mutations in two different modules and what modules are affected.
We may also need an "escape hatch" for dispatching mutations in root scope from any module:
dispatch('@someGlobalMutation')
dispatch('@rootModule:mutation')
And a module can listen to global mutations using the same syntax:
mutations: {
'@someGlobalMutation': state => {
// state is still local state
}
}
As for separating methods for mutations and actions - this is also something I thought about. Maybe we keep dispatch (since it's already been used with mutations) and use call for actions. action itself is not a verb so it feels weird. call seems to signify the "side-effect-ness" of actions pretty well.
Feels kind of weird though, all other libraries teach us to dispatch actions, and then Vuex would call actions and dispatch mutations.
I agree with the separation, just not with the naming.
We may also need an "escape hatch" for dispatching mutations in root scope from any module:
dispatch('@someRootMutation')
dispatch('@rootModule:mutation')
That would be nice. Maybe even consider them global (or application-wide) instead of root-scoped, and let any module issue and react to global mutations and actions.
UPDATE: or even invert the logic, and make "normal" mutations global, and @-mutations local. This will basically keep things compatible with current Vuex.
Also, should new Vuex encourage state: () => <state> instead of state: <state>, now that modules will be essentially reusable?
Keeping actions to work with only one module/mutation sounds a bit wired to me. Imagine I need to implement some module to collect stats for my app. With redux I can just attach reducer to my store and make it respond to actions I need. With Vuex I forced to be more explicit and duplicate dispatch calls of needed actions to perform additional mutations.
I think the design concept is very reasonable. In my developments, I always prefix or suffix mutation names for a related module. (and also I do it on Redux)
And I also agree with @simplesmiler. Explicitly dispatching multiple mutations is good, but I think sometimes we want to dispatch some mutations globally.
For example, imagine an app that can search some complex data and show various visualization on one page. I want to reset all state of previous search for each search query submission.
In my opinion, global registration would be better than global dispatch because global dispatch can accidentally execute unexpected mutations.
// normal mutation name
const RESET = 'reset'
// global mutation name
// e.g. prefixed with special character is global
const GLOBAL_RESET = '#reset'
const someModule = {
state: { value: '' },
mutations: {
[RESET] (state) { // register under the namespace
state.value = ''
}
[GLOBAL_RESET] (state) { // register to global
state.value = ''
}
}
}
// RESET is namespaced
store.dispatch(`someModule:${RESET}`)
// GLOBAL_RESET is not namespaced
store.dispatch(GLOBAL_RESET)
I basically agree all the concept and ideas and @blake-newman. And I think that we should be provided the useful Vuex API I/F for user.
@OEvgeny even in Redux it feels weird using a reducer for collecting app analytics - a middleware seems more appropriate. So in Vuex you'd just write a plugin for that purpose.
@yyx990803 thanks for response. I think there are different types of stats that can be collected. Some of them we don't need to process on the server side, some we need to collect before processing, and some we will use to show in featured parts of our app.
I like what with redux we can continue changing our store logic without touching whole app. As an example we can rewrite some parts of our store to fit new needs and implement new components/views for our new state without breaking or modifying our actions and current components/views. We can mix up together new and old parts of our store until it's needed. So, it gives more flexibility for further development.
@OEvgeny I don't think namespaced modules would make it any harder - I'm not sure what aspects in the proposal makes you think that way?
@yyx990803 I think it's all about forcing mutations inside modules to be namespaced. Then each time when I change structure of my store, I will be forced to change actions to fit this changes. I think it can be hard to do in some cases.
As an example redux also gives the ability to namespace actions without forcing to do it. It allows developer to decide not only how store organized but how actions will affect it.
@OEvgeny
mapStateToProps connections that are affected. AlsogetState() are affected too. If your stateWith an option to operate on global scope you have my thumbs up.
@yyx990803
mapStateToProps and some actions which use getState(). But there are cases when it is not needed. For example we can add new reducer to our store and get it to work with existing actions while we are working on some new features/components and migrate existing components which rely on "old" part of state later.Mutations inside modules become namespaced
I'm agree with @simplesmiler about some option to achieve global actions behavior.
Actually, now that I think about it, there's no need for auto-namespacing, because users can namespace the mutations/actions themselves. This does leave the potential for namespace clashes, but the chance seems quite low. All we really need is auto state-resolving for module actions.
For all those interested, the proposal has been heavily revised. Feedback welcome.
Just my 2c on mapGetters and mapActions...
Imagine a app with thousand components.
Each component file exports an Object.
All requirements are in actions/getters files.
component.js just exports an Object, without requiring anything.
Looks very clean.
Requiring vuex in every component file would ruin this beauty.
Perhaps there is a chance to reconsider these mappers?
Why not using a simple convention?
Like methods/computed accepts both strings and functions.
If a string given, use a store action/getter.
methods: {
a: 'a', // use a store action
b: () => {},
...otherMethods
}
And same for getters
computed: {
a: 'a', // use a store getter
b: () => {}, // compute here
...otherStuff
}
I like the use of mapGetters and mapActions, it's what I've originally thought of! Glad to see it being mentioned to assist with development.
The terms seem reasonable to me and I invite the change, but others including those coming from Redux may be unfamiliar. I wouldn't care if they were unchanged, there are much worse terms given for certain concepts like _cough_ OpenGL _cough_, and development still continues on.
The most important change in this proposal would be the modular getters and actions, for certain. Really helps in big projects. The composable actions are very nice with the promise support. I like this proposal!
@sleewoo that kind of implicitness is too much for an optional library like Vuex. When you see mapGetters and mapActions, the intentions are very clear because you see that they are imported from vuex.
makes sense.
just "realised" i treat vuex as the main piece in the stack, others being just "effects" :)
I'd love for our designers / frontend developers / template authors to be able to declare getters much like we do props.
<my-component v-for="item in items" :item="item" v-map-getters="['a', 'b', 'c']">
</my-component>
@theotherzach you can just do :a="$store.getters.a".
Can we use Vuex 2.0 with Vue 1.0?
@pdcmoreira Yes, Vuex 2.0 works with Vue 1.0
Would a mapMutations function make sense? I'm looking to reduce the boilerplate of creating actions from mutations. I'm currently upgrading an existing app to 2.0 and I have a lot of actions that just pass through to a mutation.
Example:
const actions = {
restoreMedia({ commit }, { media }) {
commit('restoreMedia', { media });
},
clearCollection({ commit }, { collection }) {
commit('clearCollection', { collection });
},
setMediaOrder({ commit }, { order }) {
commit('setMediaOrder', { order });
},
updateCustomProperty({ commit }, { media, prop, value }) {
commit('updateCustomProperty', { media, prop, value });
},
};
Alternatively, alt.js has a generateActions function for cases like this, maybe something similar would be handy?
@sebastiandedeyne yep, this is really trivial to implement: https://github.com/vuejs/vuex/blob/next/examples/todomvc/vuex/actions.js#L8-L10 although it might be a good idea to ship it so you can just import it as needed
The boilerplate for the simple case isn't great, that's for sure. Vue alone for single components or components nested 1 deep feels amazing. Vuex for complex shared actions that commit multiple mutations, also great.
What isn't great is when I just need to share simple data across large-ish app, especially if I got that data from the server, especially if I'm providing optimistic updates and potentially server error validations for multiple fields. I'm constantly making the "wrong" decision about where stuff should go with regards to individual components vs actions vs mutations.
On Jul 6, 2016, at 1:40 PM, Sebastian De Deyne [email protected] wrote:
Would a mapMutations function make sense? I'm looking to reduce the boilerplate of creating actions from mutations. I'm currently upgrading an existing app to 2.0 and I have a lot of actions that just pass through to a mutation.
Example:
const actions = {
restoreMedia({ commit }, { media }) { commit('restoreMedia', { media }); }, clearCollection({ commit }, { collection }) { commit('clearCollection', { collection }); }, setMediaOrder({ commit }, { order }) { commit('setMediaOrder', { order }); }, updateCustomProperty({ commit }, { media, prop, value }) { commit('updateCustomProperty', { media, prop, value }); },};
Alternatively, alt.js has a generateActions function for cases like this, maybe something similar would be handy?http://alt.js.org/docs/createActions/
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
@theotherzach not quite understanding your second paragraph. If the data is shared by multiple components then it should obviously be in the store. As for actions vs mutations, the rule is pretty simple: the only thing mutations do is changing the state. It gets a value, sets the value, that's it. Anything else that is related to the store goes in to actions.
I'll write up one of my more painful experiences involving forms in a day or two. I'm currently prepping my Vue.js talk at tomorrow's Chicago HTML 5 meetup.
On Jul 6, 2016, at 3:29 PM, Evan You [email protected] wrote:
@theotherzach not quite understanding your second paragraph. If the data is shared by multiple components then it should obviously be in the store. As for actions vs mutations, the rule is pretty simple: the only thing mutations do is changing the state. It gets a value, sets the value, that's it. Anything else that is related to the store goes in to actions.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.
@sebastiandedeyne yep, this is really trivial to implement: https://github.com/vuejs/vuex/blob/next/examples/todomvc/vuex/actions.js#L8-L10 although it might be a good idea to ship it so you can just import it as needed
In case anyone's interested, I also added a function to generate actions from all mutations to my application.
const makeAction = (type) => (
({ commit }, payload) => commit(type, payload)
);
const makeActions = mutations => (
Object.keys(mutations).reduce((actions, type) => {
actions[type] = makeAction(type);
return actions;
}, {})
);
const mutations = { /* ... */ };
const actions = {
...makeActions(mutations),
/* Custom actions... */
};
Thank you @yyx990803 for Vuex 2.0 changes. Especially for dynamically registering nested store modules - I use Vue instances a lot, as an auto-registering, lazy-loaded widgets, using vue-element and Webpack.
I would like to propose some changes/improvements so we can auto register nested store modules in Vue component instances.
Currently, using Vuex 2.0, my implementation looks like this:
http://www.webpackbin.com/EktD1IdUb
If you will look at widget.js you will see that on created() I manually trigger this.$store.module with this._uid name.
I would like to propose further simplifying this case. There is an example in widget.pseudocode.js file, showing how it might look like:
storeModule is auto registered in store when creating Vue instance, simillary to storethis._uidthis._uidall storeModule mutations and action storeModule(with _uid), when using commit or dispatch we can execute all mutations/action from $parent's and $children also - that way store.commit('INCREMENT') will trigger all INCREMENT in this widget/component but not others I would love to here Your opinion on this. I do not insist that my 'pseudo code' is a good idea. I'm just looking for some advices from you guys how to best handle situations like this - when you have to use store for the same components and auto register store module (e.g. using mixin).
Keep up great work, regards!
I'm not sure how me posting my own poorly written code, despite how badly I feel about it, is self importance. I don't feel important. I feel like maybe I'm not as good a coder as I thought I was because I can't seem to make Vuex work for me in a low friction way.
@theotherzach As I understand, in this discussion on new [email protected] design, new propositions are warmly welcomed but not noise, which can be triggered by to many comments.
I don't want to write in @fnlctrl name but maybe you could just combine your comments into one comment and put code examples in external JSFiddle, providing just link. This would highly increase readability of this post and hopefully help in designing better [email protected] :)
@theotherzach Can you please combine all your code on a jsfiddle and remove the comments as @karol-f said, please? That'd improve the readability of the thread 😄
@theotherzach Nice misuse of Github. You really should post this code in the vue.js forums or make a new issue, not put this in a discussion for the future of Vuex, and try to make suggestions when you have not even grasped the current fundamentals! I'm really trying to hold back negative comments, please keep in mind for the future that posting (irrelevant content) many times can annoy some of the subscribers of the issue (email goes straight to my phone).
Please do what @posva said to do.
Edit: Thanks
I apologize. You won't see me here again.
@theotherzach I'd appreciate you still share that code in a proper env like jsfiddle 😅
No need to leave 😉
I love everything about the proposal and new features and will be moving to this version as soon as I get some time to refactor.
My only question is regarding module getters receiving the sub state tree: I currently normalize all my api requests and put the different entities in different modules. This will cause all my getters to live on the root store when I want to denormalize an item. Any reason why the module getters can't receive the full state? Is it just to align with the module mutations?
@theotherzach long snippets are more appropriate in a gist, and a proposal, especially one that directly contradicts this design, would be more fitting as a separate issue.
That said, I think your usage (from my memory of glancing over what you posted before) were indeed missing a few points about Vuex:
isLoadingUser should most likely be component local state. In most cases, you'd extract state into the store for two purposes:If you simply put every single property in a big component into Vuex, you will most likely end up with more code and no obvious gain.
{{ $store.state.someData }}.Finally, if you don't think it's worth the extra code to gain trackability of your state (as shown from your proposal), you are probably better off just stay with component local state + the simple store pattern mentioned here.
@posva Sorry for my over-reaction but I'm late on this project and exhausted. In short I find the following based on my experiences. I hope that I'm using Vuex wrong, but even if that's the case then perhaps this points to evidence that Vuex is easy to use wrong.
https://gist.github.com/theotherzach/92ddb73af8f9e4c8ab70ca82a49c8fc1
@thoughts1053 I think it's probably a good idea to expose an extra rootState for module getters/mutations/actions.
@yyx990803, hopefully last questions regarding getters:
getCommentsForPost(postId).getPost(postId) prevent unnecessary re-renders of other components?@thoughts1053 You hit the nail on the head on both points. I find myself doing _1_ a lot, and _2_ would make life so much easier.
Currently in 1.0 when you call a getter from a getter, it requires passing in the state/store to the next getter, and putting each getter into an object that can be accessed by all getters. Would be nice to give each getter some way of calling another getter like how you would in a component this.cartItems vs getters.cartItems(store). Even nicer to provide arguments, example this.cartItems(accountId).
@yyx990803
I think it would be helpful to have default mutators/actions that perform a "set" behavior and thus not require explicit boilerplate declarations. Having to write custom get/set code tends to be the exception, not the rule, imho. This provides the benefits of track ability while reducing the amount of code needed.
@thoughts1053
Concerning 1.:
That is now possible with 2.0.0.-rc3, and geters not also have access to the rootState in modules.
Concerning 2.:
I don't think this in nessessary. To me, there are two scenarios where a parameter might seem to be useful, but is not:
this.$store. Getters should be pure functions to be re-usable independently from component state, so they cannot access local state like a compute prop in a component can.
A getter in the store would make not much sense to me anyway, as the operation is only meant for that component anyway.
comments) as well as the filter criterion; currentPost. In that situation you don't need to receive the currentPost as a parameter because it is already available in the store. Especially sice now we can use other getters in a getter, this should provide more than enough flexibility.@LinusBorg Thanks! I saw the release last night.
You've also answered both my questions regarding passing parameters to getters. #1 was my main concern, but creating a local computed property with this.$store makes sense. Thanks again.
@theotherzach
Looking at the gist you posted, that should probably be split up into some state submodules to make it more maintanable.
concerning the boilerplate when having async actions: The 2.0 design proposal actually makes this much easier since async actions now should return a Promise:
// in a component's method:
this.loading = true
store.dispatch('doSomething', { id: 1 })
.then(function (result) {
this.loading = false
})
.catch(function(err){
this.loading = false
// call this async action again, and // or handle error display ...
})
I just upgraded to [email protected] and as a result have two small suggestions:
mapActions and mapGetters should map ALL available actions/getters if they are called without any parameters.mapActions and mapGetters with the Object spread operator is very neat but I only realized that the Object spread operator is part of the ES7 draft spec after I ran into many issues (eslint does not support it by default, buble requires a polyfill). I suggest adding the following sentence to the documentation: "The Object spread operator is part of the ES7 specification. Please verify that your toolchain is properly configured to support this operator."@analog-nico about 2). I only had to use this - https://babeljs.io/docs/plugins/transform-object-rest-spread/. No other setup was needed in my case. I agree however about the need of info in documentation.
I didn't test it yet, so... does Object.assign() work?
computed: Object.assign({},
localComputed() {/*...*/},
mapGetters(['a', 'b', 'c', 'd'])
),
methods: Object.assign({},
localMethod() {/*...*/},
mapActions(['b'])
)
??
@karol-f True, as you say, the note in the docs is exactly my point. Likely any toolchain will easily support the operator. But since it is ES7, chances are, it's not supported by default. So it is better having the note than letting more people like me turning their toolchain inside out. ;)
@NicolasParada Object.assign is a good ES6 alternative. Your code works if you add curly braces around localComputed and localMethod. However, Object.assign needs a polyfill to run in ES5 environments. Babel likely adds one automatically. For buble you have to add it yourself.
@analog-nico Ah, of course, I forgot them.
@yyx990803 what's the recommended way regarding getters with parameters in Vuex 2.0? I used them as helpers, e.g. for some calendar I have v-for looping through days and getting them using getDay() helper as such:
function getDayIndex(weekIndex, weekDayIndex) {
return weekIndex*c.WEEK_DAY_COUNT + weekDayIndex
}
export const getDay = ({calendar}) => (weekIndex, weekDayIndex) => {
return calendar.days[getDayIndex(weekIndex, weekDayIndex)]
}
@yyx990803 I get error dispatch undefined. FYI I'm using vuex 2.3. what's wrong?
This is not a support forum. Please ask questions on forum.vuejs.org
Also, please provide code that we and other people on the forum can analyse to solve your problem.
Most helpful comment
For all those interested, the proposal has been heavily revised. Feedback welcome.