Create an accessor instance of a namespaced module of Vuex store.
npm i vuex-namespace-accessor
Create an accessor with createAccessor
function like
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import counter from './counter';
// NOTE: the module MUST be 'namespaced: true'
const store = new Vuex.Store({
state: {},
modules: {
counter,
},
});
import { createAccessor } from 'vuex-namespace-accessor';
export const $counter = createAccessor(store, 'counter');
Then use that accessor to access the namespaced module like
import { $counter } from '@/store';
// Access module state
console.log($counter.state.count);
// Access module getters
console.log($counter.getters.half);
// Commit
$counter.commit('inc', { amount: 10 });
// Dispatch
$counter.dispatch('incAsync', { amount: 20, delay: 500 });
// Watch
const unwatch = $counter.watch(
(state, getters) => {
// state = $counter.state
// getters = $counter.getters
return getters.half;
}, () => {
// Do something
}, {
immediate: false,
deep: false,
});
)
See ./example/js/src/store directory for more detail.
The store
attribute of createAccessor
can be a function which return a store
instance.
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
import counter from './counter';
import { createAccessor } from 'vuex-namespace-accessor';
export const $counter = createAccessor(() => store, 'counter');
export const store = new Vuex.Store({
state: {},
modules: {
counter,
},
});
If createAccessor
is used with type annotations in vuex-type-helper style, the accessor becomes type-safe like.
import Vue from 'vue';
import Vuex, { Store } from 'vuex';
Vue.use(Vuex);
import counter from './counter';
const store = new Vuex.Store({
state: {},
mutations: {},
actions: {},
modules: {
counter,
},
});
export default store;
import { createAccessor } from 'vuex-namespace-accessor';
interface CounterState {
count: number;
}
interface CounterGetters {
half: number;
}
interface CounterMutations {
inc: {
amount: number;
};
}
interface CounterActions {
incAsync: {
amount: number;
delay: number;
};
}
export const $counter = createAccessor<
CounterState,
CounterGetters,
CounterMutations,
CounterActions
>(store, 'counter');
Then the accessor ($counter
) is type-safe.
import { $counter } from '@/store';
// OK
console.log($counter.state.count);
// Fail
console.log($counter.state.foo);
// OK
console.log($counter.getters.half);
// Fail
console.log($counter.getters.foo);
// OK
$counter.commit('inc', { amount: 10 });
// Fail
$counter.commit('inc', { amount: 'foo' });
$counter.commit('inc', {});
$counter.commit('foo');
// OK
$counter.dispatch('incAsync', { amount: 20, delay: 500 });
// Fail
$counter.dispatch('incAsync', { amount: 20 });
$counter.dispatch('incAsync', { foo: 20 });
$counter.dispatch('foo');
// OK
$counter.watch(
s => s.count,
() => {
console.log('changed');
},
);
$counter.watch(
(_, g) => g.half,
() => {
console.log('changed');
},
);
// Fail
$counter.watch(
s => s.half,
() => {
console.log('changed');
},
);
$counter.watch(
(_, g) => g.count,
() => {
console.log('changed');
},
);
See ./example/ts/src/store directory for more detail.
interface Accessor<State, Getters, Mutations, Actions> {
state: State;
getters: Getters;
commit<K extends keyof Mutations>(type: K, payload: Mutations[K]): void;
commit<K extends keyof Mutations>(payloadWithType: { type: K } & Mutations[K]): void;
dispatch<K extends keyof Actions>(type: K, payload: Actions[K]): Promise<any> | void;
dispatch<K extends keyof Actions>(payloadWithType: { type: K } & Actions[K]): Promise<any> | void;
watch(
getter: (state: S, getters: G) => any,
callback: () => void,
options?: {
deep?: boolean;
immediate?: boolean;
},
): () => void;
}
function createAccessor<S, G, M, A>(
store: Store<any> || (() => Store<any>),
path: string | string[],
): Accessor<S, G, M, A>;