• Vue3+Typescript封装Pinia插件,优雅管理所有请求的loading效果


    为什么要管理项目的loading效果?

    1. 页面数据是通过接口获取的,所有是异步的,那么用户操作下去的时候如果没有loading效果那么页面会显得很呆
    2. 如果一个接口一个loading,那么项目会存在非常多的冗余代码,例如下面这样
    .....一些变量....
    const loading = ref(false);
    
    const handler = async()=>{
    	loading.value = true;
    	let res = await fetchXXX();
    	loading.value = false;
    	....其他业务...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    从上面可以看出,只要涉及到异步操作,都有可能需要一个loading效果,所以如何优雅处理页面loaidng效果呢?

    参考dva-loading到实现原理,通过拦截用户的异步操作,统一管理loading效果,但是dva只有react版本,因为内部是封装了redux和redux-sagas,好在Vue有Pinia这个新的状态管理工具,他是支持自定义插件,并且这个新的状态管理库非常好用good!(具体可以自己去dva查看dva官网

    在这里插入图片描述
    详细的用法我就不在这里细说了,直接说这个插件如果实现吧,我参考了一个git库,修改了他的一些代码,现在也用在自己的项目中,还不错,这个是作者的git地址git仓库
    我改后的代码如下

    import type { PiniaPluginContext } from 'pinia'
    import { reactive } from 'vue';
    
    export function PiniaLoading({ options, store }: PiniaPluginContext) {
      if (options.actions) {
        const $loading  = reactive<Record<string,boolean>>({});
        Object.keys(options.actions).forEach((actionKey) => {
          const originAction = options.actions[actionKey]
          const action = function(this: unknown, ...args : unknown[]) {
            const rtn = originAction.apply(this, args)
            if (rtn instanceof Promise) {
              $loading[actionKey] = false;
              return new Promise((resolve, reject) => {
    						$loading[actionKey] = true;
                rtn
                  .then(resolve)
                  .catch(reject)
                  .finally(() => {
                    $loading[actionKey] = false;
                  })
              })
            } else {
              return rtn
            }
          }
          store[actionKey] = action
        })
      	store.$loading = $loading
      }
    }
    declare module 'pinia' {
    	// eslint-disable-next-line
    	export interface PiniaCustomProperties<Id, S, G, A> {
    		$loading: {
    			[K in keyof A as A[K] extends (...args: any) => Promise<any> ? K : never]: boolean;
    		};
    	}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39

    然后在页面中就可以直接使用模块名下的对应方法名来当作loading的值了,插件内部会自动处理好loading效果;

    例如这个权限模块下有个action方法是用来获取角色群仙列表的

    1:对应模块的action中的一个方法
    在这里插入图片描述
    2.在对应的.Vue文件中导入该模块(pinia用法)
    在这里插入图片描述
    3.直接使用模块名.$loading.模块的action对应的方法名就是loading
    在这里插入图片描述

    到此大功告成、不需要每次都定义loading、然后手动改变loading的值了,有兴趣的小伙伴可以自己导进去玩玩

  • 相关阅读:
    RKMEDIA--VO的使用
    从转载阿里开源项目 Egg.js 技术文档引发的“版权纠纷”,看宽松的 MIT 许可该如何用?...
    kubectl系列(五)-kubectl get
    定时任务相关
    相对免赔额和绝对免赔额是什么意思,有什么区别?
    spring boot项目资源跳转,及引入js、css和a标签,ajax等的路径问题
    文档外发控制与安全:实现高效协作与数据安全的关键
    8 ActiveMQ的持久化
    vue2与vue3生命周期的区别
    ffmpeg - 笔记
  • 原文地址:https://blog.csdn.net/weixin_42341232/article/details/126203630