简单写写和使用useRequest-vue版

在以往的业务项目中,我们经常会被 loading 状态的管理等重复的功能实现所困扰。每次开启一个新项目都需要重新实现一遍,这是一项重复的工作。

VueRequest 的目的是为开发人员提供一种方便、快速的方式来管理 API 状态。通过简单的配置,可以省去那些繁琐的任务,专注于业务核心的开发。

官网地址

以下是我自己简单实现的,当练练手了。

使用 - 一开始就请求数据

js 复制代码
const request_apiStatisticsFormat = () => apiStatisticsFormat({ schoolId, groupCode, groupType });

const { data, loading, error, run } = useRequest(request_apiStatisticsFormat, {
  ready: true,
  deps: [],
  isShowLoading: true,
  onSuccess: (res) => {
    console.log('res', res);
    studentList.value = res.data.studentList;
  },
});

api的相关方法

ts 复制代码
export const apiGetStudentList = (params: IParams) =>
  get<ResponseData>(`/k12-app-api/api/npad/homeSchool/interact/getStudentList`, {
    params,
    // baseURL: 'https://ntteacher-api-test1.test.xdf.cn',
  });
export const apiStatisticsFormat = (params: IParams) => formatApiFn(apiGetStudentList, params, mockData);

export interface ResponseData<T = any> {
  data: T;
  status?: string | number;
  code?: string | number;
  msg: string;
  success: boolean;
}

export const formatApiFn = async (
  apiFn: (params?: any) => Promise<any>,
  params: any,
  mockData?: any,
) => {
  try {
    const sleep = (time: number) => new Promise((resolve) => setTimeout(resolve, time));
    mockData && (await sleep(1000));
    const res = mockData ? mockData : await apiFn(params);
    const { data } = res;
    if (data.success) return data;
    return Promise.reject(data);
  } catch (error) {
    return Promise.reject(error);
  }
};

使用 - 等特定条件才开始请求数据

ts 复制代码
const { data, loading, error, run } = useRequest(request_apiStatisticsFormat, {
  // ready取决于isSelectedDate
  ready: isSelectedDate.value,
  // date值一旦发生变化,就重新请求数据
  deps: [date],
  isShowLoading: true,
  onSuccess: (res) => {
    console.log('res', res);
    const {
      connectStudentList: connectStudentListData,
      notConnectStudentList: notConnectStudentListData,
      statistics: statisticsData,
    } = res.data || {};
  },
});

useRequest

ts 复制代码
import { ref, watch } from 'vue';
import { Toast } from 'vant';
import Vue from 'vue';
Vue.use(Toast);
interface IUseRequestOptions {
  // 请求成功回调
  onSuccess?: (data: any) => void;
  // 请求错误回调
  onError?: (error: any) => void;
  // 请求结束回调
  onFinally?: () => void;
  // 是否自动执行,默认是true
  ready?: boolean;
  // 监听依赖项,自动执行
  deps?: any[];
  // 初始data值
  initialData?: any;
  // 是否展示加载效果
  isShowLoading?: boolean;
}

export const useRequest = (
  requestFn: (requestParams?: any) => Promise<any>,
  options?: IUseRequestOptions,
) => {
  // 初始值
  const data = ref(options?.initialData);
  // loading 是否正在请求
  const loading = ref(false);
  // error 是否请求错误
  const error = ref(null);
  const { onSuccess, onError, onFinally, ready, deps, isShowLoading } = options || {
    ready: true,
  };
  // run就是请求函数
  const run = async () => {
    error.value = null;
    // 正在请求中
    loading.value = true;
    console.log('开始', 1);
    try {
      // 请求函数
      const res = await requestFn();
      // 请求结果赋值
      data.value = res;
      console.log('成功', res);
      error.value = null;
      // 请求成功回调
      onSuccess && onSuccess(res);
    } catch (err) {
      console.log('错误', err);
      // 请求错误赋值
      error.value = err;
      // 请求错误回调
      onError && onError(err);
    } finally {
      // 请求结束
      loading.value = false;
      // 请求结束回调
      onFinally && onFinally();
    }
  };
  // 是否展示加载效果
  isShowLoading &&
    watch(loading, (newVal) => {
      newVal
        ? Toast.loading({
            message: '加载中...',
            forbidClick: true,
          })
        : Toast.clear();
    });
  // 如果ready为true,自动执行
  ready && run();
  // 监听依赖项,自动执行
  watch(deps, () => {
    run();
  });

  return {
    data,
    loading,
    error,
    run,
  };
};

错误状态显示

vue 复制代码
<!-- 使用     
https://blog-huahua.oss-cn-beijing.aliyuncs.com/blog/code/error_3.png
https://blog-huahua.oss-cn-beijing.aliyuncs.com/blog/code/empty3.png

<StatusPage v-if="error" text="网络错误,请稍候再试~" :showLoadBtn="true" @reload="run" :isFullScreen="true"/>

<StatusPage v-if="isEmpty" text="暂无数据~" :isFullScreen="true" />

局部空数据展示
<div v-if="isEmpty" style="height: 300px; position: relative" >
  <StatusPage :isFullScreen="false" text="暂无数据~" />
</div>
 -->
<template>
  <div class="status-page-box" :class="{isFullScreen}">
    <div class="empty-error-page" id="pageError">
      <img class="img" src="@/assets/images/error.png" />
      <div class="des">{{ text }}</div>
      <div v-if="showLoadBtn" class="btn-load" @click="$emit('reload')">重新加载</div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { defineProps } from 'vue';
const props = defineProps({
  text: {
    type: String,
  },
  isFullScreen: {
    type: Boolean,
    default: true,
  },
  showLoadBtn: {
    type: Boolean,
    default: false,
  },
});
</script>

<style scoped lang="less">
.isFullScreen{
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background: #fafafa;
  z-index: 888888;
}
.empty-error-page {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 8;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  text-align: center;
  .img {
    width: 102px;
    height: 97px;
  }
  .des {
    font-size: 14px;
    color: #999;
  }
  .btn-load {
    font-size: 14px;
    font-weight: 500;
    color: #ffffff;
    line-height: 34px;

    width: 100px;
    height: 34px;
    background: linear-gradient(180deg, #49d391 0%, #34d0aa 100%);
    border-radius: 17px;
    text-align: center;
    margin-top: 20px;
  }
}
</style>
相关推荐
foxhuli22932 分钟前
禁止ifrmare标签上的文件,实现自动下载功能,并且隐藏工具栏
前端
青皮桔1 小时前
CSS实现百分比水柱图
前端·css
失落的多巴胺1 小时前
使用deepseek制作“喝什么奶茶”随机抽签小网页
javascript·css·css3·html5
DataGear1 小时前
如何在DataGear 5.4.1 中快速制作SQL服务端分页的数据表格看板
javascript·数据库·sql·信息可视化·数据分析·echarts·数据可视化
影子信息1 小时前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月1 小时前
1.vue权衡的艺术
前端·vue.js·开源
RunsenLIu1 小时前
基于Vue.js + Node.js + MySQL实现的图书销售管理系统
vue.js·mysql·node.js
样子20181 小时前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿1 小时前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
翻滚吧键盘1 小时前
vue文本插值
javascript·vue.js·ecmascript