diff --git a/src/helpers.js b/src/helpers.js index 7c28563b9..5fca8b987 100644 --- a/src/helpers.js +++ b/src/helpers.js @@ -25,12 +25,18 @@ export const mapState = normalizeNamespace((namespace, states) => { export const mapMutations = normalizeNamespace((namespace, mutations) => { const res = {} normalizeMap(mutations).forEach(({ key, val }) => { - val = namespace + val res[key] = function mappedMutation (...args) { - if (namespace && !getModuleByNamespace(this.$store, 'mapMutations', namespace)) { - return + let commit = this.$store.commit + if (namespace) { + const module = getModuleByNamespace(this.$store, 'mapMutations', namespace) + if (!module) { + return + } + commit = module.context.commit } - return this.$store.commit.apply(this.$store, [val].concat(args)) + return typeof val === 'function' + ? val.apply(this, [commit].concat(args)) + : commit.apply(this.$store, [val].concat(args)) } }) return res @@ -59,12 +65,18 @@ export const mapGetters = normalizeNamespace((namespace, getters) => { export const mapActions = normalizeNamespace((namespace, actions) => { const res = {} normalizeMap(actions).forEach(({ key, val }) => { - val = namespace + val res[key] = function mappedAction (...args) { - if (namespace && !getModuleByNamespace(this.$store, 'mapActions', namespace)) { - return + let dispatch = this.$store.dispatch + if (namespace) { + const module = getModuleByNamespace(this.$store, 'mapActions', namespace) + if (!module) { + return + } + dispatch = module.context.dispatch } - return this.$store.dispatch.apply(this.$store, [val].concat(args)) + return typeof val === 'function' + ? val.apply(this, [dispatch].concat(args)) + : dispatch.apply(this.$store, [val].concat(args)) } }) return res diff --git a/test/unit/helpers.spec.js b/test/unit/helpers.spec.js index 5c7030845..1bc0fc409 100644 --- a/test/unit/helpers.spec.js +++ b/test/unit/helpers.spec.js @@ -133,6 +133,27 @@ describe('Helpers', () => { expect(store.state.count).toBe(0) }) + it('mapMutations (function)', () => { + const store = new Vuex.Store({ + state: { count: 0 }, + mutations: { + inc (state, amount) { + state.count += amount + } + } + }) + const vm = new Vue({ + store, + methods: mapMutations({ + plus (commit, amount) { + commit('inc', amount + 1) + } + }) + }) + vm.plus(42) + expect(store.state.count).toBe(43) + }) + it('mapMutations (with namespace)', () => { const store = new Vuex.Store({ modules: { @@ -159,6 +180,32 @@ describe('Helpers', () => { expect(store.state.foo.count).toBe(0) }) + it('mapMutations (function with namepsace)', () => { + const store = new Vuex.Store({ + modules: { + foo: { + namespaced: true, + state: { count: 0 }, + mutations: { + inc (state, amount) { + state.count += amount + } + } + } + } + }) + const vm = new Vue({ + store, + methods: mapMutations('foo', { + plus (commit, amount) { + commit('inc', amount + 1) + } + }) + }) + vm.plus(42) + expect(store.state.foo.count).toBe(43) + }) + it('mapGetters (array)', () => { const store = new Vuex.Store({ state: { count: 0 }, @@ -347,6 +394,23 @@ describe('Helpers', () => { expect(b).toHaveBeenCalled() }) + it('mapActions (function)', () => { + const a = jasmine.createSpy() + const store = new Vuex.Store({ + actions: { a } + }) + const vm = new Vue({ + store, + methods: mapActions({ + foo (dispatch, arg) { + dispatch('a', arg + 'bar') + } + }) + }) + vm.foo('foo') + expect(a.calls.argsFor(0)[1]).toBe('foobar') + }) + it('mapActions (with namespace)', () => { const a = jasmine.createSpy() const b = jasmine.createSpy() @@ -375,6 +439,28 @@ describe('Helpers', () => { expect(b).toHaveBeenCalled() }) + it('mapActions (function with namespace)', () => { + const a = jasmine.createSpy() + const store = new Vuex.Store({ + modules: { + foo: { + namespaced: true, + actions: { a } + } + } + }) + const vm = new Vue({ + store, + methods: mapActions('foo/', { + foo (dispatch, arg) { + dispatch('a', arg + 'bar') + } + }) + }) + vm.foo('foo') + expect(a.calls.argsFor(0)[1]).toBe('foobar') + }) + it('createNamespacedHelpers', () => { const actionA = jasmine.createSpy() const actionB = jasmine.createSpy() diff --git a/types/helpers.d.ts b/types/helpers.d.ts index e7c791e73..0770ef38c 100644 --- a/types/helpers.d.ts +++ b/types/helpers.d.ts @@ -1,4 +1,5 @@ import Vue = require("vue"); +import { Dispatch, Commit } from './index'; type Dictionary = { [key: string]: T }; type Computed = () => any; @@ -15,6 +16,17 @@ interface MapperWithNamespace { (namespace: string, map: Dictionary): Dictionary; } +interface FunctionMapper { + (map: Dictionary<(this: typeof Vue, fn: F, ...args: any[]) => any>): Dictionary; +} + +interface FunctionMapperWithNamespace { + ( + namespace: string, + map: Dictionary<(this: typeof Vue, fn: F, ...args: any[]) => any> + ): Dictionary; +} + interface MapperForState { ( map: Dictionary<(this: typeof Vue, state: S, getters: any) => any> @@ -30,9 +42,9 @@ interface MapperForStateWithNamespace { interface NamespacedMappers { mapState: Mapper & MapperForState; - mapMutations: Mapper; + mapMutations: Mapper & FunctionMapper; mapGetters: Mapper; - mapActions: Mapper; + mapActions: Mapper & FunctionMapper; } export declare const mapState: Mapper @@ -41,12 +53,16 @@ export declare const mapState: Mapper & MapperForStateWithNamespace; export declare const mapMutations: Mapper - & MapperWithNamespace; + & MapperWithNamespace + & FunctionMapper + & FunctionMapperWithNamespace; export declare const mapGetters: Mapper & MapperWithNamespace; export declare const mapActions: Mapper - & MapperWithNamespace; + & MapperWithNamespace + & FunctionMapper + & FunctionMapperWithNamespace; export declare function createNamespacedHelpers(namespace: string): NamespacedMappers; diff --git a/types/test/helpers.ts b/types/test/helpers.ts index c6a3304be..0ebaed6ae 100644 --- a/types/test/helpers.ts +++ b/types/test/helpers.ts @@ -61,29 +61,83 @@ new Vue({ mapActions({ h: "h" }), + mapActions({ + g (dispatch, a: string, b: number, c: boolean): void { + dispatch('g', { a, b, c }) + dispatch({ + type: 'g', + a, + b, + c + }) + } + }), mapActions('foo', ["g"]), mapActions('foo', { h: "h" }), + mapActions('foo', { + g (dispatch, a: string, b: number, c: boolean): void { + dispatch('g', { a, b, c }) + dispatch({ + type: 'g', + a, + b, + c + }) + } + }), mapMutations(["i"]), mapMutations({ j: "j" }), + mapMutations({ + i (commit, a: string, b: number, c: boolean): void { + commit('i', { a, b, c }) + commit({ + type: 'i', + a, + b, + c + }) + } + }), mapMutations('foo', ["i"]), mapMutations('foo', { j: "j" }), + mapMutations('foo', { + i (commit, a: string, b: number, c: boolean): void { + commit('i', { a, b, c }) + commit({ + type: 'i', + a, + b, + c + }) + } + }), helpers.mapActions(["m"]), helpers.mapActions({ m: "m" }), + helpers.mapActions({ + m (dispatch, value: string) { + dispatch('m', value) + } + }), helpers.mapMutations(["n"]), helpers.mapMutations({ n: "n" }), + helpers.mapMutations({ + n (commit, value: string) { + commit('m', value) + } + }), { otherMethod () {}