Răsfoiți Sursa

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
katashin 7 ani în urmă
părinte
comite
be15f32c00
4 a modificat fișierele cu 180 adăugiri și 12 ștergeri
  1. 20 8
      src/helpers.js
  2. 86 0
      test/unit/helpers.spec.js
  3. 20 4
      types/helpers.d.ts
  4. 54 0
      types/test/helpers.ts

+ 20 - 8
src/helpers.js

@@ -25,12 +25,18 @@ export const mapState = normalizeNamespace((namespace, states) => {
 export const mapMutations = normalizeNamespace((namespace, mutations) => {
 export const mapMutations = normalizeNamespace((namespace, mutations) => {
   const res = {}
   const res = {}
   normalizeMap(mutations).forEach(({ key, val }) => {
   normalizeMap(mutations).forEach(({ key, val }) => {
-    val = namespace + val
     res[key] = function mappedMutation (...args) {
     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
   return res
@@ -59,12 +65,18 @@ export const mapGetters = normalizeNamespace((namespace, getters) => {
 export const mapActions = normalizeNamespace((namespace, actions) => {
 export const mapActions = normalizeNamespace((namespace, actions) => {
   const res = {}
   const res = {}
   normalizeMap(actions).forEach(({ key, val }) => {
   normalizeMap(actions).forEach(({ key, val }) => {
-    val = namespace + val
     res[key] = function mappedAction (...args) {
     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
   return res

+ 86 - 0
test/unit/helpers.spec.js

@@ -133,6 +133,27 @@ describe('Helpers', () => {
     expect(store.state.count).toBe(0)
     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)', () => {
   it('mapMutations (with namespace)', () => {
     const store = new Vuex.Store({
     const store = new Vuex.Store({
       modules: {
       modules: {
@@ -159,6 +180,32 @@ describe('Helpers', () => {
     expect(store.state.foo.count).toBe(0)
     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)', () => {
   it('mapGetters (array)', () => {
     const store = new Vuex.Store({
     const store = new Vuex.Store({
       state: { count: 0 },
       state: { count: 0 },
@@ -347,6 +394,23 @@ describe('Helpers', () => {
     expect(b).toHaveBeenCalled()
     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)', () => {
   it('mapActions (with namespace)', () => {
     const a = jasmine.createSpy()
     const a = jasmine.createSpy()
     const b = jasmine.createSpy()
     const b = jasmine.createSpy()
@@ -375,6 +439,28 @@ describe('Helpers', () => {
     expect(b).toHaveBeenCalled()
     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', () => {
   it('createNamespacedHelpers', () => {
     const actionA = jasmine.createSpy()
     const actionA = jasmine.createSpy()
     const actionB = jasmine.createSpy()
     const actionB = jasmine.createSpy()

+ 20 - 4
types/helpers.d.ts

@@ -1,4 +1,5 @@
 import Vue = require("vue");
 import Vue = require("vue");
+import { Dispatch, Commit } from './index';
 
 
 type Dictionary<T> = { [key: string]: T };
 type Dictionary<T> = { [key: string]: T };
 type Computed = () => any;
 type Computed = () => any;
@@ -15,6 +16,17 @@ interface MapperWithNamespace<R> {
   (namespace: string, map: Dictionary<string>): Dictionary<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 {
 interface MapperForState {
   <S>(
   <S>(
     map: Dictionary<(this: typeof Vue, state: S, getters: any) => any>
     map: Dictionary<(this: typeof Vue, state: S, getters: any) => any>
@@ -30,9 +42,9 @@ interface MapperForStateWithNamespace {
 
 
 interface NamespacedMappers {
 interface NamespacedMappers {
   mapState: Mapper<Computed> & MapperForState;
   mapState: Mapper<Computed> & MapperForState;
-  mapMutations: Mapper<MutationMethod>;
+  mapMutations: Mapper<MutationMethod> & FunctionMapper<Commit, MutationMethod>;
   mapGetters: Mapper<Computed>;
   mapGetters: Mapper<Computed>;
-  mapActions: Mapper<ActionMethod>;
+  mapActions: Mapper<ActionMethod> & FunctionMapper<Dispatch, ActionMethod>;
 }
 }
 
 
 export declare const mapState: Mapper<Computed>
 export declare const mapState: Mapper<Computed>
@@ -41,12 +53,16 @@ export declare const mapState: Mapper<Computed>
   & MapperForStateWithNamespace;
   & MapperForStateWithNamespace;
 
 
 export declare const mapMutations: Mapper<MutationMethod>
 export declare const mapMutations: Mapper<MutationMethod>
-  & MapperWithNamespace<MutationMethod>;
+  & MapperWithNamespace<MutationMethod>
+  & FunctionMapper<Commit, MutationMethod>
+  & FunctionMapperWithNamespace<Commit, MutationMethod>;
 
 
 export declare const mapGetters: Mapper<Computed>
 export declare const mapGetters: Mapper<Computed>
   & MapperWithNamespace<Computed>;
   & MapperWithNamespace<Computed>;
 
 
 export declare const mapActions: Mapper<ActionMethod>
 export declare const mapActions: Mapper<ActionMethod>
-  & MapperWithNamespace<ActionMethod>;
+  & MapperWithNamespace<ActionMethod>
+  & FunctionMapper<Dispatch, ActionMethod>
+  & FunctionMapperWithNamespace<Dispatch, ActionMethod>;
 
 
 export declare function createNamespacedHelpers(namespace: string): NamespacedMappers;
 export declare function createNamespacedHelpers(namespace: string): NamespacedMappers;

+ 54 - 0
types/test/helpers.ts

@@ -61,29 +61,83 @@ new Vue({
     mapActions({
     mapActions({
       h: "h"
       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', ["g"]),
     mapActions('foo', {
     mapActions('foo', {
       h: "h"
       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(["i"]),
     mapMutations({
     mapMutations({
       j: "j"
       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', ["i"]),
     mapMutations('foo', {
     mapMutations('foo', {
       j: "j"
       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"]),
     helpers.mapActions({
     helpers.mapActions({
       m: "m"
       m: "m"
     }),
     }),
+    helpers.mapActions({
+      m (dispatch, value: string) {
+        dispatch('m', value)
+      }
+    }),
 
 
     helpers.mapMutations(["n"]),
     helpers.mapMutations(["n"]),
     helpers.mapMutations({
     helpers.mapMutations({
       n: "n"
       n: "n"
     }),
     }),
+    helpers.mapMutations({
+      n (commit, value: string) {
+        commit('m', value)
+      }
+    }),
 
 
     {
     {
       otherMethod () {}
       otherMethod () {}