Skip to content

Commit be15f32

Browse files
ktsnyyx990803
authored andcommitted
feat: allow to passing functions in mapActions/mapMutations (fix #750) (#924)
* feat: allow to pass function value in mapActions/mapMutations * feat: extend mapActions/mapMutations types for function usage
1 parent b16f2f7 commit be15f32

File tree

4 files changed

+180
-12
lines changed

4 files changed

+180
-12
lines changed

src/helpers.js

+20-8
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@ export const mapState = normalizeNamespace((namespace, states) => {
2525
export const mapMutations = normalizeNamespace((namespace, mutations) => {
2626
const res = {}
2727
normalizeMap(mutations).forEach(({ key, val }) => {
28-
val = namespace + val
2928
res[key] = function mappedMutation (...args) {
30-
if (namespace && !getModuleByNamespace(this.$store, 'mapMutations', namespace)) {
31-
return
29+
let commit = this.$store.commit
30+
if (namespace) {
31+
const module = getModuleByNamespace(this.$store, 'mapMutations', namespace)
32+
if (!module) {
33+
return
34+
}
35+
commit = module.context.commit
3236
}
33-
return this.$store.commit.apply(this.$store, [val].concat(args))
37+
return typeof val === 'function'
38+
? val.apply(this, [commit].concat(args))
39+
: commit.apply(this.$store, [val].concat(args))
3440
}
3541
})
3642
return res
@@ -59,12 +65,18 @@ export const mapGetters = normalizeNamespace((namespace, getters) => {
5965
export const mapActions = normalizeNamespace((namespace, actions) => {
6066
const res = {}
6167
normalizeMap(actions).forEach(({ key, val }) => {
62-
val = namespace + val
6368
res[key] = function mappedAction (...args) {
64-
if (namespace && !getModuleByNamespace(this.$store, 'mapActions', namespace)) {
65-
return
69+
let dispatch = this.$store.dispatch
70+
if (namespace) {
71+
const module = getModuleByNamespace(this.$store, 'mapActions', namespace)
72+
if (!module) {
73+
return
74+
}
75+
dispatch = module.context.dispatch
6676
}
67-
return this.$store.dispatch.apply(this.$store, [val].concat(args))
77+
return typeof val === 'function'
78+
? val.apply(this, [dispatch].concat(args))
79+
: dispatch.apply(this.$store, [val].concat(args))
6880
}
6981
})
7082
return res

test/unit/helpers.spec.js

+86
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,27 @@ describe('Helpers', () => {
133133
expect(store.state.count).toBe(0)
134134
})
135135

136+
it('mapMutations (function)', () => {
137+
const store = new Vuex.Store({
138+
state: { count: 0 },
139+
mutations: {
140+
inc (state, amount) {
141+
state.count += amount
142+
}
143+
}
144+
})
145+
const vm = new Vue({
146+
store,
147+
methods: mapMutations({
148+
plus (commit, amount) {
149+
commit('inc', amount + 1)
150+
}
151+
})
152+
})
153+
vm.plus(42)
154+
expect(store.state.count).toBe(43)
155+
})
156+
136157
it('mapMutations (with namespace)', () => {
137158
const store = new Vuex.Store({
138159
modules: {
@@ -159,6 +180,32 @@ describe('Helpers', () => {
159180
expect(store.state.foo.count).toBe(0)
160181
})
161182

183+
it('mapMutations (function with namepsace)', () => {
184+
const store = new Vuex.Store({
185+
modules: {
186+
foo: {
187+
namespaced: true,
188+
state: { count: 0 },
189+
mutations: {
190+
inc (state, amount) {
191+
state.count += amount
192+
}
193+
}
194+
}
195+
}
196+
})
197+
const vm = new Vue({
198+
store,
199+
methods: mapMutations('foo', {
200+
plus (commit, amount) {
201+
commit('inc', amount + 1)
202+
}
203+
})
204+
})
205+
vm.plus(42)
206+
expect(store.state.foo.count).toBe(43)
207+
})
208+
162209
it('mapGetters (array)', () => {
163210
const store = new Vuex.Store({
164211
state: { count: 0 },
@@ -347,6 +394,23 @@ describe('Helpers', () => {
347394
expect(b).toHaveBeenCalled()
348395
})
349396

397+
it('mapActions (function)', () => {
398+
const a = jasmine.createSpy()
399+
const store = new Vuex.Store({
400+
actions: { a }
401+
})
402+
const vm = new Vue({
403+
store,
404+
methods: mapActions({
405+
foo (dispatch, arg) {
406+
dispatch('a', arg + 'bar')
407+
}
408+
})
409+
})
410+
vm.foo('foo')
411+
expect(a.calls.argsFor(0)[1]).toBe('foobar')
412+
})
413+
350414
it('mapActions (with namespace)', () => {
351415
const a = jasmine.createSpy()
352416
const b = jasmine.createSpy()
@@ -375,6 +439,28 @@ describe('Helpers', () => {
375439
expect(b).toHaveBeenCalled()
376440
})
377441

442+
it('mapActions (function with namespace)', () => {
443+
const a = jasmine.createSpy()
444+
const store = new Vuex.Store({
445+
modules: {
446+
foo: {
447+
namespaced: true,
448+
actions: { a }
449+
}
450+
}
451+
})
452+
const vm = new Vue({
453+
store,
454+
methods: mapActions('foo/', {
455+
foo (dispatch, arg) {
456+
dispatch('a', arg + 'bar')
457+
}
458+
})
459+
})
460+
vm.foo('foo')
461+
expect(a.calls.argsFor(0)[1]).toBe('foobar')
462+
})
463+
378464
it('createNamespacedHelpers', () => {
379465
const actionA = jasmine.createSpy()
380466
const actionB = jasmine.createSpy()

types/helpers.d.ts

+20-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import Vue = require("vue");
2+
import { Dispatch, Commit } from './index';
23

34
type Dictionary<T> = { [key: string]: T };
45
type Computed = () => any;
@@ -15,6 +16,17 @@ interface MapperWithNamespace<R> {
1516
(namespace: string, map: Dictionary<string>): Dictionary<R>;
1617
}
1718

19+
interface FunctionMapper<F, R> {
20+
(map: Dictionary<(this: typeof Vue, fn: F, ...args: any[]) => any>): Dictionary<R>;
21+
}
22+
23+
interface FunctionMapperWithNamespace<F, R> {
24+
(
25+
namespace: string,
26+
map: Dictionary<(this: typeof Vue, fn: F, ...args: any[]) => any>
27+
): Dictionary<R>;
28+
}
29+
1830
interface MapperForState {
1931
<S>(
2032
map: Dictionary<(this: typeof Vue, state: S, getters: any) => any>
@@ -30,9 +42,9 @@ interface MapperForStateWithNamespace {
3042

3143
interface NamespacedMappers {
3244
mapState: Mapper<Computed> & MapperForState;
33-
mapMutations: Mapper<MutationMethod>;
45+
mapMutations: Mapper<MutationMethod> & FunctionMapper<Commit, MutationMethod>;
3446
mapGetters: Mapper<Computed>;
35-
mapActions: Mapper<ActionMethod>;
47+
mapActions: Mapper<ActionMethod> & FunctionMapper<Dispatch, ActionMethod>;
3648
}
3749

3850
export declare const mapState: Mapper<Computed>
@@ -41,12 +53,16 @@ export declare const mapState: Mapper<Computed>
4153
& MapperForStateWithNamespace;
4254

4355
export declare const mapMutations: Mapper<MutationMethod>
44-
& MapperWithNamespace<MutationMethod>;
56+
& MapperWithNamespace<MutationMethod>
57+
& FunctionMapper<Commit, MutationMethod>
58+
& FunctionMapperWithNamespace<Commit, MutationMethod>;
4559

4660
export declare const mapGetters: Mapper<Computed>
4761
& MapperWithNamespace<Computed>;
4862

4963
export declare const mapActions: Mapper<ActionMethod>
50-
& MapperWithNamespace<ActionMethod>;
64+
& MapperWithNamespace<ActionMethod>
65+
& FunctionMapper<Dispatch, ActionMethod>
66+
& FunctionMapperWithNamespace<Dispatch, ActionMethod>;
5167

5268
export declare function createNamespacedHelpers(namespace: string): NamespacedMappers;

types/test/helpers.ts

+54
Original file line numberDiff line numberDiff line change
@@ -61,29 +61,83 @@ new Vue({
6161
mapActions({
6262
h: "h"
6363
}),
64+
mapActions({
65+
g (dispatch, a: string, b: number, c: boolean): void {
66+
dispatch('g', { a, b, c })
67+
dispatch({
68+
type: 'g',
69+
a,
70+
b,
71+
c
72+
})
73+
}
74+
}),
6475
mapActions('foo', ["g"]),
6576
mapActions('foo', {
6677
h: "h"
6778
}),
79+
mapActions('foo', {
80+
g (dispatch, a: string, b: number, c: boolean): void {
81+
dispatch('g', { a, b, c })
82+
dispatch({
83+
type: 'g',
84+
a,
85+
b,
86+
c
87+
})
88+
}
89+
}),
6890

6991
mapMutations(["i"]),
7092
mapMutations({
7193
j: "j"
7294
}),
95+
mapMutations({
96+
i (commit, a: string, b: number, c: boolean): void {
97+
commit('i', { a, b, c })
98+
commit({
99+
type: 'i',
100+
a,
101+
b,
102+
c
103+
})
104+
}
105+
}),
73106
mapMutations('foo', ["i"]),
74107
mapMutations('foo', {
75108
j: "j"
76109
}),
110+
mapMutations('foo', {
111+
i (commit, a: string, b: number, c: boolean): void {
112+
commit('i', { a, b, c })
113+
commit({
114+
type: 'i',
115+
a,
116+
b,
117+
c
118+
})
119+
}
120+
}),
77121

78122
helpers.mapActions(["m"]),
79123
helpers.mapActions({
80124
m: "m"
81125
}),
126+
helpers.mapActions({
127+
m (dispatch, value: string) {
128+
dispatch('m', value)
129+
}
130+
}),
82131

83132
helpers.mapMutations(["n"]),
84133
helpers.mapMutations({
85134
n: "n"
86135
}),
136+
helpers.mapMutations({
137+
n (commit, value: string) {
138+
commit('m', value)
139+
}
140+
}),
87141

88142
{
89143
otherMethod () {}

0 commit comments

Comments
 (0)