简单写写和使用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>
相关推荐
别拿曾经看以后~36 分钟前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死39 分钟前
导航栏及下拉菜单的实现
前端·css·css3
川石课堂软件测试42 分钟前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
problc1 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter