[Vue3] useLoading封装:优雅地设置Loading状态

5,304 阅读1分钟

一、背景

日常开发中,经常需要使用v-loading指令展示加载动画,表示数据正在加载中。

通常在ajax请求前后对v-loading绑定值进行改变。如:

const queryData = ()=>{
    isLoading = true;
    ajax(url,data).then().finally(()=>{
        isLoading = false;
    })
}

当页面中有个请求时,需要在相应请求都完成后再将v-loading设置成false。

Vue3中,推荐使用composition api对模块进行封装,据此,个人设计了useLoading

二、useLoading 代码

// useLoading.ts
import { ref, computed } from "vue";

export const useLoading = () => {
  // 使用number类型的loadingIndex,而不是boolean类型,用于有多个请求的场景
  const loadingIndex = ref(0);
  
  // 计算属性,根据loadingIndex的值判断为true/false
  const isLoading = computed(() => {
    return loadingIndex.value <= 0 ? false : true;
  });
  
  // 进入loading,loadingIndex的值加1
  const enterLoading = () => {
    loadingIndex.value += 1;
  };
  
  // 退出loading,loadingIndex的值减1
  const quitLoading = () => {
    if (loadingIndex.value > 0) {
      loadingIndex.value -= 1;
    } else {
      console.warn("no need quit loading");
    }
  };

  // loadingWrapper方法,自动完成进入/退出loading的设置
  const loadingWrapper = <T>(promise: Promise<T>) => {
    return new Promise<void>((resolve, reject) => {
      // 进入loading
      enterLoading();
      promise.finally(() => {
        // 退出loading
        quitLoading();
        resolve();
      });
    });
  };
  return {
    isLoading,
    enterLoading,
    quitLoading,
    loadingWrapper,
  };
};

三、使用示例

// 在业务组件中
<template>
    <div v-loading="isLoading"></div>
</template>
<script lang='ts' setup>
import { useLoading } from '@/hooks'
const { isLoading, loadingWrapper } = useLoading()
// 请求数据的方法
const queryDataList = () => {
    // 使用loadingWrapper,自动完成进入/退出loading的设置
    loadingWrapper(DataApi.queryData({}).then(res => {
        let data = res.data.data.list
        data = clearButtonType(data)
        clearEmptyChildren(data)
        allMenuList.value = data
    }))
}
</script>