为什么要管理项目的loading效果?
- 页面数据是通过接口获取的,所有是异步的,那么用户操作下去的时候如果没有loading效果那么页面会显得很呆
- 如果一个接口一个loading,那么项目会存在非常多的冗余代码,例如下面这样
.....一些变量....
const loading = ref(false);
const handler = async()=>{
loading.value = true;
let res = await fetchXXX();
loading.value = false;
....其他业务...
}
从上面可以看出,只要涉及到异步操作,都有可能需要一个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;
};
}
}
然后在页面中就可以直接使用模块名下的对应方法名来当作loading的值了,插件内部会自动处理好loading效果;
例如这个权限模块下有个action方法是用来获取角色群仙列表的
1:对应模块的action中的一个方法
2.在对应的.Vue文件中导入该模块(pinia用法)
3.直接使用模块名.$loading.模块的action对应的方法名就是loading
到此大功告成、不需要每次都定义loading、然后手动改变loading的值了,有兴趣的小伙伴可以自己导进去玩玩