扩展 Vue3 全家桶vuex 组合Api方便批量引入

395 阅读3分钟

自定义封装了

useMapState,
useMapMutations,
useMapGetters,
useMapActions,
useComputed

用法:

import { useMapState, useComputed } from '@/utils/vuec'
let {api_token, lang}= useComputed(useMapState('user', ['api_token', 'lang']))
console.log(api_token.value, lang.value)

废话不多说直接上代码

/*
1、集成vue、vuex、vue-router、vue-i18n组合式api导入;
2、同时封装vuex组合式api:useMapState, useMapMutations, useMapGetters, useMapActions, useComputed 方便vuex 批量引入
*/
import { useStore } from 'vuex'
import { computed } from 'vue'
export * from 'vue'
export * from 'vuex'
export * from 'vue-router'
export * from 'vue-i18n'
function isObject(obj) {
return obj !== null && typeof obj === 'object'
}
/**
* Normalize the map
* normalizeMap([1, 2, 3]) => [ { key: 1, val: 1 }, { key: 2, val: 2 }, { key: 3, val: 3 } ]
* normalizeMap({a: 1, b: 2, c: 3}) => [ { key: 'a', val: 1 }, { key: 'b', val: 2 }, { key: 'c', val: 3 } ]
* @param {Array|Object} map
* @return {Object}
*/
function normalizeMap(map) {
if (!isValidMap(map)) {
return []
}
return Array.isArray(map)
? map.map(function (key) { return ({ key: key, val: key }); })
: Object.keys(map).map(function (key) { return ({ key: key, val: map[key] }); })
}
/**
* Validate whether given map is valid or not
* @param {*} map
* @return {Boolean}
*/
function isValidMap(map) {
return Array.isArray(map) || isObject(map)
}
/**
* Return a function expect two param contains namespace and map. it will normalize the namespace and then the param's function will handle the new namespace and the map.
* @param {Function} fn
* @return {Function}
*/
function normalizeNamespace(fn) {
return function (namespace, map) {
if (typeof namespace !== 'string') {
map = namespace;
namespace = '';
} else if (namespace.charAt(namespace.length - 1) !== '/') {
namespace += '/';
}
return fn(namespace, map)
}
}
/**
* Search a special module from store by namespace. if module not exist, print error message.
* @param {Object} store
* @param {String} helper
* @param {String} namespace
* @return {Object}
*/
function getModuleByNamespace(store, helper, namespace) {
var module = store._modulesNamespaceMap[namespace];
if (!module) {
console.error(("[vuex] module namespace not found in " + helper + "(): " + namespace));
}
return module
}
const useMapState = normalizeNamespace(function (namespace, states) {
var res = {};
if (!isValidMap(states)) {
console.error('[vuex] mapState: mapper parameter must be either an Array or an Object');
}
var store = useStore()
normalizeMap(states).forEach(function (ref) {
var key = ref.key;
var val = ref.val;
res[key] = function mappedState() {
var state = store.state;
var getters = store.getters;
if (namespace) {
var module = getModuleByNamespace(store, 'mapState', namespace);
if (!module) {
return
}
state = module.context.state;
getters = module.context.getters;
}
return typeof val === 'function'
? val.call(this, state, getters)
: state[val]
};
// mark vuex getter for devtools
res[key].vuex = true;
});
return res
});
/* Transfrom an useMapState or an useMapGetters to an computed object*/
const useComputed = function(obj){
if (!isObject(obj)) {
console.error('[vuex] useComputed: obj parameter must be either an useMapState or an useMapGetters');
}
return Object.entries(obj).reduce((obj, item)=>{
obj[item[0]] = computed(item[1])
return obj
}, {})
}
/**
* Reduce the code which written in Vue.js for committing the mutation
* @param {String} [namespace] - Module's namespace
* @param {Object|Array} mutations # Object's item can be a function which accept `commit` function as the first param, it can accept anthor params. You can commit mutation and do any other things in this function. specially, You need to pass anthor params from the mapped function.
* @return {Object}
*/
const useMapMutations = normalizeNamespace(function (namespace, mutations) {
var res = {};
if (!isValidMap(mutations)) {
console.error('[vuex] mapMutations: mapper parameter must be either an Array or an Object');
}
var store = useStore()
normalizeMap(mutations).forEach(function (ref) {
var key = ref.key;
var val = ref.val;
res[key] = function mappedMutation() {
var args = [], len = arguments.length;
while (len--) args[len] = arguments[len];
// Get the commit method from store
var commit = store.commit;
if (namespace) {
var module = getModuleByNamespace(store, 'mapMutations', namespace);
if (!module) {
return
}
commit = module.context.commit;
}
return typeof val === 'function'
? val.apply(this, [commit].concat(args))
: commit.apply(store, [val].concat(args))
};
});
return res
});
/**
* Reduce the code which written in Vue.js for getting the getters
* @param {String} [namespace] - Module's namespace
* @param {Object|Array} getters
* @return {Object}
*/
const useMapGetters = normalizeNamespace(function (namespace, getters) {
var res = {};
if (!isValidMap(getters)) {
console.error('[vuex] mapGetters: mapper parameter must be either an Array or an Object');
}
var store = useStore()
normalizeMap(getters).forEach(function (ref) {
var key = ref.key;
var val = ref.val;
// The namespace has been mutated by normalizeNamespace
val = namespace + val;
res[key] = function mappedGetter() {
if (namespace && !getModuleByNamespace(store, 'mapGetters', namespace)) {
return
}
if (!(val in store.getters)) {
console.error(("[vuex] unknown getter: " + val));
return
}
return store.getters[val]
};
// mark vuex getter for devtools
res[key].vuex = true;
});
return res
});
/**
* Reduce the code which written in Vue.js for dispatch the action
* @param {String} [namespace] - Module's namespace
* @param {Object|Array} actions # Object's item can be a function which accept `dispatch` function as the first param, it can accept anthor params. You can dispatch action and do any other things in this function. specially, You need to pass anthor params from the mapped function.
* @return {Object}
*/
const useMapActions = normalizeNamespace(function (namespace, actions) {
var res = {};
if (!isValidMap(actions)) {
console.error('[vuex] mapActions: mapper parameter must be either an Array or an Object');
}
var store = useStore()
normalizeMap(actions).forEach(function (ref) {
var key = ref.key;
var val = ref.val;
res[key] = function mappedAction() {
var args = [], len = arguments.length;
while (len--) args[len] = arguments[len];
// get dispatch function from store
var dispatch = store.dispatch;
if (namespace) {
var module = getModuleByNamespace(store, 'mapActions', namespace);
if (!module) {
return
}
dispatch = module.context.dispatch;
}
return typeof val === 'function'
? val.apply(this, [dispatch].concat(args))
: dispatch.apply(store, [val].concat(args))
};
});
return res
});
export {
useMapState,
useMapMutations,
useMapGetters,
useMapActions,
useComputed
}