Skip to content

Commit 5027b73

Browse files
committed
support namespace in helpers
1 parent dcb568e commit 5027b73

File tree

3 files changed

+163
-15
lines changed

3 files changed

+163
-15
lines changed

src/helpers.js

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,41 @@
1-
export function mapState (states) {
1+
export const mapState = normalizeNamespace((namespace, states) => {
22
const res = {}
33
normalizeMap(states).forEach(({ key, val }) => {
44
res[key] = function mappedState () {
5+
let state = this.$store.state
6+
let getters = this.$store.getters
7+
if (namespace) {
8+
const module = this.$store._modulesNamespaceMap[namespace]
9+
if (!module) {
10+
warnNamespace('mapState', namespace)
11+
return
12+
}
13+
state = module.state
14+
getters = module.context.getters
15+
}
516
return typeof val === 'function'
6-
? val.call(this, this.$store.state, this.$store.getters)
7-
: this.$store.state[val]
17+
? val.call(this, state, getters)
18+
: state[val]
819
}
920
})
1021
return res
11-
}
22+
})
1223

13-
export function mapMutations (mutations) {
24+
export const mapMutations = normalizeNamespace((namespace, mutations) => {
1425
const res = {}
1526
normalizeMap(mutations).forEach(({ key, val }) => {
27+
val = namespace + val
1628
res[key] = function mappedMutation (...args) {
1729
return this.$store.commit.apply(this.$store, [val].concat(args))
1830
}
1931
})
2032
return res
21-
}
33+
})
2234

23-
export function mapGetters (getters) {
35+
export const mapGetters = normalizeNamespace((namespace, getters) => {
2436
const res = {}
2537
normalizeMap(getters).forEach(({ key, val }) => {
38+
val = namespace + val
2639
res[key] = function mappedGetter () {
2740
if (!(val in this.$store.getters)) {
2841
console.error(`[vuex] unknown getter: ${val}`)
@@ -31,20 +44,37 @@ export function mapGetters (getters) {
3144
}
3245
})
3346
return res
34-
}
47+
})
3548

36-
export function mapActions (actions) {
49+
export const mapActions = normalizeNamespace((namespace, actions) => {
3750
const res = {}
3851
normalizeMap(actions).forEach(({ key, val }) => {
52+
val = namespace + val
3953
res[key] = function mappedAction (...args) {
4054
return this.$store.dispatch.apply(this.$store, [val].concat(args))
4155
}
4256
})
4357
return res
44-
}
58+
})
4559

4660
function normalizeMap (map) {
4761
return Array.isArray(map)
4862
? map.map(key => ({ key, val: key }))
4963
: Object.keys(map).map(key => ({ key, val: map[key] }))
5064
}
65+
66+
function normalizeNamespace (fn) {
67+
return (namespace, map) => {
68+
if (typeof namespace !== 'string') {
69+
map = namespace
70+
namespace = ''
71+
} else if (namespace.charAt(namespace.length - 1) !== '/') {
72+
namespace += '/'
73+
}
74+
return fn(namespace, map)
75+
}
76+
}
77+
78+
function warnNamespace (helper, namespace) {
79+
console.error(`[vuex] module namespace not found in ${helper}(): ${namespace}`)
80+
}

src/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Store {
2323
this._mutations = Object.create(null)
2424
this._wrappedGetters = Object.create(null)
2525
this._modules = new ModuleCollection(options)
26+
this._modulesNamespaceMap = Object.create(null)
2627
this._subscribers = []
2728
this._watcherVM = new Vue()
2829

@@ -81,10 +82,7 @@ class Store {
8182
})
8283
this._subscribers.forEach(sub => sub(mutation, this.state))
8384

84-
if (
85-
process.env.NODE_ENV !== 'production' &&
86-
options && options.hasOwnProperty('silent')
87-
) {
85+
if (options && options.silent) {
8886
console.warn(
8987
`[vuex] mutation type: ${type}. Silent option has been removed. ` +
9088
'Use the filter functionality in the vue-devtools'
@@ -170,6 +168,7 @@ function resetStore (store) {
170168
store._actions = Object.create(null)
171169
store._mutations = Object.create(null)
172170
store._wrappedGetters = Object.create(null)
171+
store._modulesNamespaceMap = Object.create(null)
173172
const state = store.state
174173
// init all modules
175174
installModule(store, state, [], store._modules.root, true)
@@ -223,6 +222,11 @@ function installModule (store, rootState, path, module, hot) {
223222
const isRoot = !path.length
224223
const namespace = store._modules.getNamespace(path)
225224

225+
// register in namespace map
226+
if (namespace) {
227+
store._modulesNamespaceMap[namespace] = module
228+
}
229+
226230
// set state
227231
if (!isRoot && !hot) {
228232
const parentState = getNestedState(rootState, path.slice(0, -1))
@@ -232,7 +236,7 @@ function installModule (store, rootState, path, module, hot) {
232236
})
233237
}
234238

235-
const local = makeLocalContext(store, namespace)
239+
const local = module.context = makeLocalContext(store, namespace)
236240

237241
module.forEachMutation((mutation, key) => {
238242
const namespacedType = namespace + key

test/unit/helpers.spec.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,31 @@ describe('Helpers', () => {
3939
expect(vm.a).toBe(4)
4040
})
4141

42+
it('mapState (with namespace)', () => {
43+
const store = new Vuex.Store({
44+
modules: {
45+
foo: {
46+
namespaced: true,
47+
state: { a: 1 },
48+
getters: {
49+
b: state => state.a + 1
50+
}
51+
}
52+
}
53+
})
54+
const vm = new Vue({
55+
store,
56+
computed: mapState('foo', {
57+
a: (state, getters) => {
58+
return state.a + getters.b
59+
}
60+
})
61+
})
62+
expect(vm.a).toBe(3)
63+
store.state.foo.a++
64+
expect(vm.a).toBe(5)
65+
})
66+
4267
it('mapMutations (array)', () => {
4368
const store = new Vuex.Store({
4469
state: { count: 0 },
@@ -78,6 +103,32 @@ describe('Helpers', () => {
78103
expect(store.state.count).toBe(0)
79104
})
80105

106+
it('mapMutations (with namespace)', () => {
107+
const store = new Vuex.Store({
108+
modules: {
109+
foo: {
110+
namespaced: true,
111+
state: { count: 0 },
112+
mutations: {
113+
inc: state => state.count++,
114+
dec: state => state.count--
115+
}
116+
}
117+
}
118+
})
119+
const vm = new Vue({
120+
store,
121+
methods: mapMutations('foo', {
122+
plus: 'inc',
123+
minus: 'dec'
124+
})
125+
})
126+
vm.plus()
127+
expect(store.state.foo.count).toBe(1)
128+
vm.minus()
129+
expect(store.state.foo.count).toBe(0)
130+
})
131+
81132
it('mapGetters (array)', () => {
82133
const store = new Vuex.Store({
83134
state: { count: 0 },
@@ -135,6 +186,41 @@ describe('Helpers', () => {
135186
expect(vm.b).toBe(true)
136187
})
137188

189+
it('mapGetters (with namespace)', () => {
190+
const store = new Vuex.Store({
191+
modules: {
192+
foo: {
193+
namespaced: true,
194+
state: { count: 0 },
195+
mutations: {
196+
inc: state => state.count++,
197+
dec: state => state.count--
198+
},
199+
getters: {
200+
hasAny: ({ count }) => count > 0,
201+
negative: ({ count }) => count < 0
202+
}
203+
}
204+
}
205+
})
206+
const vm = new Vue({
207+
store,
208+
computed: mapGetters('foo', {
209+
a: 'hasAny',
210+
b: 'negative'
211+
})
212+
})
213+
expect(vm.a).toBe(false)
214+
expect(vm.b).toBe(false)
215+
store.commit('foo/inc')
216+
expect(vm.a).toBe(true)
217+
expect(vm.b).toBe(false)
218+
store.commit('foo/dec')
219+
store.commit('foo/dec')
220+
expect(vm.a).toBe(false)
221+
expect(vm.b).toBe(true)
222+
})
223+
138224
it('mapActions (array)', () => {
139225
const a = jasmine.createSpy()
140226
const b = jasmine.createSpy()
@@ -177,4 +263,32 @@ describe('Helpers', () => {
177263
vm.bar()
178264
expect(b).toHaveBeenCalled()
179265
})
266+
267+
it('mapActions (with namespace)', () => {
268+
const a = jasmine.createSpy()
269+
const b = jasmine.createSpy()
270+
const store = new Vuex.Store({
271+
modules: {
272+
foo: {
273+
namespaced: true,
274+
actions: {
275+
a,
276+
b
277+
}
278+
}
279+
}
280+
})
281+
const vm = new Vue({
282+
store,
283+
methods: mapActions('foo/', {
284+
foo: 'a',
285+
bar: 'b'
286+
})
287+
})
288+
vm.foo()
289+
expect(a).toHaveBeenCalled()
290+
expect(b).not.toHaveBeenCalled()
291+
vm.bar()
292+
expect(b).toHaveBeenCalled()
293+
})
180294
})

0 commit comments

Comments
 (0)