Skip to content

Commit

Permalink
support namespace in helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 16, 2016
1 parent dcb568e commit 5027b73
Show file tree
Hide file tree
Showing 3 changed files with 163 additions and 15 deletions.
50 changes: 40 additions & 10 deletions src/helpers.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,41 @@
export function mapState (states) {
export const mapState = normalizeNamespace((namespace, states) => {
const res = {}
normalizeMap(states).forEach(({ key, val }) => {
res[key] = function mappedState () {
let state = this.$store.state
let getters = this.$store.getters
if (namespace) {
const module = this.$store._modulesNamespaceMap[namespace]
if (!module) {
warnNamespace('mapState', namespace)
return
}
state = module.state
getters = module.context.getters
}
return typeof val === 'function'
? val.call(this, this.$store.state, this.$store.getters)
: this.$store.state[val]
? val.call(this, state, getters)
: state[val]
}
})
return res
}
})

export function mapMutations (mutations) {
export const mapMutations = normalizeNamespace((namespace, mutations) => {
const res = {}
normalizeMap(mutations).forEach(({ key, val }) => {
val = namespace + val
res[key] = function mappedMutation (...args) {
return this.$store.commit.apply(this.$store, [val].concat(args))
}
})
return res
}
})

export function mapGetters (getters) {
export const mapGetters = normalizeNamespace((namespace, getters) => {
const res = {}
normalizeMap(getters).forEach(({ key, val }) => {
val = namespace + val
res[key] = function mappedGetter () {
if (!(val in this.$store.getters)) {
console.error(`[vuex] unknown getter: ${val}`)
Expand All @@ -31,20 +44,37 @@ export function mapGetters (getters) {
}
})
return res
}
})

export function mapActions (actions) {
export const mapActions = normalizeNamespace((namespace, actions) => {
const res = {}
normalizeMap(actions).forEach(({ key, val }) => {
val = namespace + val
res[key] = function mappedAction (...args) {
return this.$store.dispatch.apply(this.$store, [val].concat(args))
}
})
return res
}
})

function normalizeMap (map) {
return Array.isArray(map)
? map.map(key => ({ key, val: key }))
: Object.keys(map).map(key => ({ key, val: map[key] }))
}

function normalizeNamespace (fn) {
return (namespace, map) => {
if (typeof namespace !== 'string') {
map = namespace
namespace = ''
} else if (namespace.charAt(namespace.length - 1) !== '/') {
namespace += '/'
}
return fn(namespace, map)
}
}

function warnNamespace (helper, namespace) {
console.error(`[vuex] module namespace not found in ${helper}(): ${namespace}`)
}
14 changes: 9 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class Store {
this._mutations = Object.create(null)
this._wrappedGetters = Object.create(null)
this._modules = new ModuleCollection(options)
this._modulesNamespaceMap = Object.create(null)
this._subscribers = []
this._watcherVM = new Vue()

Expand Down Expand Up @@ -81,10 +82,7 @@ class Store {
})
this._subscribers.forEach(sub => sub(mutation, this.state))

if (
process.env.NODE_ENV !== 'production' &&
options && options.hasOwnProperty('silent')
) {
if (options && options.silent) {
console.warn(
`[vuex] mutation type: ${type}. Silent option has been removed. ` +
'Use the filter functionality in the vue-devtools'
Expand Down Expand Up @@ -170,6 +168,7 @@ function resetStore (store) {
store._actions = Object.create(null)
store._mutations = Object.create(null)
store._wrappedGetters = Object.create(null)
store._modulesNamespaceMap = Object.create(null)
const state = store.state
// init all modules
installModule(store, state, [], store._modules.root, true)
Expand Down Expand Up @@ -223,6 +222,11 @@ function installModule (store, rootState, path, module, hot) {
const isRoot = !path.length
const namespace = store._modules.getNamespace(path)

// register in namespace map
if (namespace) {
store._modulesNamespaceMap[namespace] = module
}

// set state
if (!isRoot && !hot) {
const parentState = getNestedState(rootState, path.slice(0, -1))
Expand All @@ -232,7 +236,7 @@ function installModule (store, rootState, path, module, hot) {
})
}

const local = makeLocalContext(store, namespace)
const local = module.context = makeLocalContext(store, namespace)

module.forEachMutation((mutation, key) => {
const namespacedType = namespace + key
Expand Down
114 changes: 114 additions & 0 deletions test/unit/helpers.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,31 @@ describe('Helpers', () => {
expect(vm.a).toBe(4)
})

it('mapState (with namespace)', () => {
const store = new Vuex.Store({
modules: {
foo: {
namespaced: true,
state: { a: 1 },
getters: {
b: state => state.a + 1
}
}
}
})
const vm = new Vue({
store,
computed: mapState('foo', {
a: (state, getters) => {
return state.a + getters.b
}
})
})
expect(vm.a).toBe(3)
store.state.foo.a++
expect(vm.a).toBe(5)
})

it('mapMutations (array)', () => {
const store = new Vuex.Store({
state: { count: 0 },
Expand Down Expand Up @@ -78,6 +103,32 @@ describe('Helpers', () => {
expect(store.state.count).toBe(0)
})

it('mapMutations (with namespace)', () => {
const store = new Vuex.Store({
modules: {
foo: {
namespaced: true,
state: { count: 0 },
mutations: {
inc: state => state.count++,
dec: state => state.count--
}
}
}
})
const vm = new Vue({
store,
methods: mapMutations('foo', {
plus: 'inc',
minus: 'dec'
})
})
vm.plus()
expect(store.state.foo.count).toBe(1)
vm.minus()
expect(store.state.foo.count).toBe(0)
})

it('mapGetters (array)', () => {
const store = new Vuex.Store({
state: { count: 0 },
Expand Down Expand Up @@ -135,6 +186,41 @@ describe('Helpers', () => {
expect(vm.b).toBe(true)
})

it('mapGetters (with namespace)', () => {
const store = new Vuex.Store({
modules: {
foo: {
namespaced: true,
state: { count: 0 },
mutations: {
inc: state => state.count++,
dec: state => state.count--
},
getters: {
hasAny: ({ count }) => count > 0,
negative: ({ count }) => count < 0
}
}
}
})
const vm = new Vue({
store,
computed: mapGetters('foo', {
a: 'hasAny',
b: 'negative'
})
})
expect(vm.a).toBe(false)
expect(vm.b).toBe(false)
store.commit('foo/inc')
expect(vm.a).toBe(true)
expect(vm.b).toBe(false)
store.commit('foo/dec')
store.commit('foo/dec')
expect(vm.a).toBe(false)
expect(vm.b).toBe(true)
})

it('mapActions (array)', () => {
const a = jasmine.createSpy()
const b = jasmine.createSpy()
Expand Down Expand Up @@ -177,4 +263,32 @@ describe('Helpers', () => {
vm.bar()
expect(b).toHaveBeenCalled()
})

it('mapActions (with namespace)', () => {
const a = jasmine.createSpy()
const b = jasmine.createSpy()
const store = new Vuex.Store({
modules: {
foo: {
namespaced: true,
actions: {
a,
b
}
}
}
})
const vm = new Vue({
store,
methods: mapActions('foo/', {
foo: 'a',
bar: 'b'
})
})
vm.foo()
expect(a).toHaveBeenCalled()
expect(b).not.toHaveBeenCalled()
vm.bar()
expect(b).toHaveBeenCalled()
})
})

0 comments on commit 5027b73

Please sign in to comment.