Skip to content

Commit

Permalink
feat: allow to passing functions in mapActions/mapMutations (fix #750) (
Browse files Browse the repository at this point in the history
#924)

* feat: allow to pass function value in mapActions/mapMutations

* feat: extend mapActions/mapMutations types for function usage
  • Loading branch information
ktsn authored and yyx990803 committed Aug 31, 2017
1 parent b16f2f7 commit be15f32
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 12 deletions.
28 changes: 20 additions & 8 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
86 changes: 86 additions & 0 deletions test/unit/helpers.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -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 },
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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()
Expand Down
24 changes: 20 additions & 4 deletions types/helpers.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Vue = require("vue");
import { Dispatch, Commit } from './index';

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

interface FunctionMapper<F, R> {
(map: Dictionary<(this: typeof Vue, fn: F, ...args: any[]) => any>): Dictionary<R>;
}

interface FunctionMapperWithNamespace<F, R> {
(
namespace: string,
map: Dictionary<(this: typeof Vue, fn: F, ...args: any[]) => any>
): Dictionary<R>;
}

interface MapperForState {
<S>(
map: Dictionary<(this: typeof Vue, state: S, getters: any) => any>
Expand All @@ -30,9 +42,9 @@ interface MapperForStateWithNamespace {

interface NamespacedMappers {
mapState: Mapper<Computed> & MapperForState;
mapMutations: Mapper<MutationMethod>;
mapMutations: Mapper<MutationMethod> & FunctionMapper<Commit, MutationMethod>;
mapGetters: Mapper<Computed>;
mapActions: Mapper<ActionMethod>;
mapActions: Mapper<ActionMethod> & FunctionMapper<Dispatch, ActionMethod>;
}

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

export declare const mapMutations: Mapper<MutationMethod>
& MapperWithNamespace<MutationMethod>;
& MapperWithNamespace<MutationMethod>
& FunctionMapper<Commit, MutationMethod>
& FunctionMapperWithNamespace<Commit, MutationMethod>;

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

export declare const mapActions: Mapper<ActionMethod>
& MapperWithNamespace<ActionMethod>;
& MapperWithNamespace<ActionMethod>
& FunctionMapper<Dispatch, ActionMethod>
& FunctionMapperWithNamespace<Dispatch, ActionMethod>;

export declare function createNamespacedHelpers(namespace: string): NamespacedMappers;
54 changes: 54 additions & 0 deletions types/test/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () {}
Expand Down

0 comments on commit be15f32

Please sign in to comment.