Vue3 封装扩展并简化Vuex在组件中的调用问题

 更新时间:2023年01月28日 09:14:43   作者:马丁的车夫  
这篇文章主要介绍了Vue3 封装扩展并简化Vuex在组件中的调用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

如果你在项目中使用了 vuex模块化,并且在项目中使用actions中函数调用频率高,推荐了解一下这种方式。

比如下面两种方式调用 ,

第一个是直接传参设置,

第二个是添加了异步ajax返回内容 在回调到等下我们要封装的js中的成功回调里,然后这个成功回调就会反馈给组件

1.创建文件utils/vueTool.js

import storage from '@/utils/storage.js';
import store from '@/store/index.js';
const { dispatch, state } = store;
/**
 * @vuexFunc 调用vuex模块中的 Actions 并异步回调结果
 * @param modules {string} 调用指定的子模块 如果是全局的可以不传
 * @param funcName {string} 调用Actions 函数名称
 * @param data  {object} 
 * @param followUp  {string / object} 
 *  {
     data:{},
     followUp:string / object
     function(res){}
    },
 * data:当前调用接口需要的参数,
 * followUp 当前接口完成回调后 继续执行更新接口的 名称和参数 可以是请求地址字符串 可以是对象携带参数
 * followUp:'URL' / followUp:{url:'请求接口地址',query:{参数}}
 * function回调函数
 */
export function vuexFunc(modules = '', funcName = '', data = {}) {
    function send(followUp = '', query = null, lock = null) {
        // 消费凭证
        if (typeof lock === 'number') {
            console.log('已消费:', lock)
            lock = true
        };
        let url = '';
        if (followUp) {
            url = followUp;
        } else {
            if (!modules && typeof modules !== 'boolean') {
                console.error('Actions函数名称是必填。');
                return;
            };
            url = `${modules?modules+'/':''}${funcName}`;
        };
        
        // 开发中使用 校验当前调用的vuex模块是否存在 
        if (process.env.NODE_ENV === 'development') {
            let modulesName = followUp ? followUp.split('/')[0] : typeof modules === 'boolean' ? funcName :modules;
            if (storage.getItem('modulesKey').indexOf(modulesName) === -1) {
                console.error(`找不到 ${modulesName} 请检查!`);
                return;
            };
        };
        let queryData = {}
        if(typeof modules === 'boolean'){
            queryData = data
            
        } else {
            queryData = followUp ? query ? query : {} :data.data && Object.keys(data.data).length?data.data:{}
        }
        dispatch(url, {
            // data: followUp ? query ? query : {} : data.data,
            data: queryData,
            callback(res) {
                // 成功
                if (res !== 'failed') {
                    if (lock) {
                        console.log('停止了')
                        return
                    };
                    if (data.callback) {
                        data.callback(res);
                    };
                    if (data.followUp && typeof data.followUp === 'string') {
                        console.log('开始后续回调')
                        send(data.followUp, null, Date.now());
                    } else if (data.followUp && Object.keys(data.followUp).length) {
                        if (!data.followUp.url) {
                            console.error('缺少后续请求的url');
                            return;
                        };
                        if (!data.followUp.hasOwnProperty('query')) {
                            console.error('query字段 缺少后续请求的参数,没有参数直接传入 string Url 形参');
                            return;
                        };
                        send(data.followUp.url, data.followUp.query, Date.now())
                    };
                    // 失败 -1
                } else if (res === 'failed') {
                    if (data.failed) {
                        data.failed(res)
                    } else {
                        console.error('接口请求失败:'+url)
                    }
                };
            }
        });
    };
    send();
}

/**
 * @getState 获取vuex中state仓库
 * @param modules {string} 仓库名称 如果是子模块就传入子模块的名称
 */
export function getState(modules = '') {
    if (!modules) {
        console.error('state仓库名称是必填。');
        return;
    };
    return state[modules]
}

2.添加开发环境中的模块验证

注意:如果你的vue3项目是使用webpack5创建的 那么这里的自动化导入文件 就不能使用,可以去看看我上篇文章中有写webpack5如何自动化导入模块

import { createStore } from 'vuex'
import actions from './actions'
import mutations from './mutations'
import storage from '@/utils/storage.js'


const modulesFiles = import.meta.glob('./modules/*/index.js', { eager: true });

const modules = Object.keys(modulesFiles).reduce(
    (modules, path) => {
        const moduleName = path.replace(/^\.\/(.*)\.\w+$/, '$1')
        modules[moduleName.split('/')[1]] = modulesFiles[path]?.default
        return modules
    }, {}
);

let modulesKey  = '';
if(process.env.NODE_ENV === 'development'){
    let obj = {...actions,...modules};
    for(let key in obj){
        modulesKey+=key+','
    };
    storage.setItem('modulesKey',modulesKey);
};
const store = createStore({
    modules,
    state: {
        name: 'allen',
        modulesKey:storage.getItem('modulesKey') || modulesKey,
    },
    mutations,
    actions,
    getters: {}
})

export default store

3.页面调用封装

actions函数的调用

import { vuexFunc, getState } from '@/utils/vueTool';

vuexFunc('子模块文件昵称','actions.js中定义的函数昵称',{
    data:{接口需要的参数,或者你要设置到仓库的值},
    callback(res){ // 请求回调
            console.log(res)
    }
});
//模式一(调用全局actions函数)
vuexFunc(false,'setStageCourse',{
    data:query,
    callback(res){
            console.log(res)
    }
});

//模式二(调用子模块函数中的actions函数)
vuexFunc('index','setStageCourse',{
    data:query,
    callback(res){
            console.log(res)
    }
});

// 模式三(调用完一个actions函数后立即执行另外一个actions函数)
这里调用完成signIn子模块中的loginByCode函数完成回调后,会立即去读取followUp的配置 也是对应了 子模块/signIn函数昵称去执行,followUp允许一个具体的函数路径或者一个对象可以配置函数要设置的值
vuexFunc('signIn','loginByCode',{
        data:{code:wxcode.value},
        followUp:'index/getConfig',
    callback(res){
        SignType.value = false
        storage.setItem('authorization',res.data.token);
        
    }
});

state仓库的使用

import {vuexFunc,getState} from '@/utils/vueTool'

// 获取全局state
let data = getState('全局state对象中定义的对象key')

// 获取子模块中的 state
// getState('子模块昵称') 获取到某个子模块中的state仓库对象
let data = getState('signIn').SigninType

最后:

这样既扩展了功能 也不需要原本的vuex 先导入 在解构 在调用,并且对actions的控制和错误也做到了颗粒化捕获,与拦截反馈,在一定程度上提高了开发过程中的程序调试。

后来我又思考了一下感觉还能继续优化,比如像vue2中使用...mapActions 和...mapState 直接返回多个函数对象,感觉这样会比较优雅,但是在项目中我已经开发过半了 所以就没有对这个进行重新改造,有兴趣的可以试试。

到此这篇关于Vue3 封装扩展并简化Vuex在组件中的调用的文章就介绍到这了,更多相关Vue3 封装扩展内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue与vue-i18n结合实现后台数据的多语言切换方法

    vue与vue-i18n结合实现后台数据的多语言切换方法

    下面小编就为大家分享一篇vue与vue-i18n结合实现后台数据的多语言切换方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • Vue.js实现的购物车功能详解

    Vue.js实现的购物车功能详解

    这篇文章主要介绍了Vue.js实现的购物车功能,结合实例形式分析了vue.js购物车的原理、数值计算及页面元素属性动态操作相关实现技巧,需要的朋友可以参考下
    2019-01-01
  • vue实现记事本案例

    vue实现记事本案例

    这篇文章主要为大家详细介绍了vue实现记事本案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 从Element日期组件源码中学到的两个工具方法技巧

    从Element日期组件源码中学到的两个工具方法技巧

    这篇文章主要介绍了从Element日期组件源码中学到的两个工具方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-08-08
  • 封装Vue Element的table表格组件的示例详解

    封装Vue Element的table表格组件的示例详解

    这篇文章主要介绍了封装Vue Element的table表格组件的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2020-08-08
  • reactive readonly嵌套对象转换功能实现详解

    reactive readonly嵌套对象转换功能实现详解

    这篇文章主要为大家介绍了reactive readonly嵌套对象转换功能实现详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • vue.extend与vue.component的区别和联系

    vue.extend与vue.component的区别和联系

    这篇文章主要介绍了vue.extend与vue.component的区别和联系,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值 ,需要的朋友可以参考下
    2018-09-09
  • vue踩坑记录之src的动态绑定赋值问题

    vue踩坑记录之src的动态绑定赋值问题

    这篇文章主要介绍了vue踩坑记录之src的动态绑定赋值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06
  • vue实现购物车加减

    vue实现购物车加减

    这篇文章主要为大家详细介绍了vue实现购物车加减,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • 深入理解Vue的过度与动画

    深入理解Vue的过度与动画

    这篇文章主要为大家介绍了Vue的过度与动画,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-11-11

最新评论