Skip to content

调用组件封装axios和loading

安装

bash
npm install antd -S
npm install axios -S

新建loading组件

路径

bash
src
├── components
   ├── common
       ├── Loading
             ├── index.css
             ├── index.tsx
             ├── loading.ts

index.css

css
.global-loading-mask {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255, 255, 255, 0.6);
  z-index: 9999;
}

index.tsx

tsx
import { Spin } from "antd";
import "./index.css";

export default function Loading() {
  return (
    <div className="global-loading-mask">
      <Spin tip="加载中666..." size="large">
        <div style={{ width: 200, height: 100 }} />
      </Spin>
    </div>
  );
}

loading.ts

ts
import { createRoot, type Root } from "react-dom/client";
import { createElement } from "react";
import Loading from "./index";

let container: HTMLDivElement | null = null;
let root: Root | null = null;

// 挂载 loading
export function mountLoading() {
  if (container) return;
  container = document.createElement("div");
  container.id = "global-loading";
  document.body.appendChild(container);
  root = createRoot(container);
  root.render(createElement(Loading));
}

// 卸载 loading
export function unmountLoading() {
  if (!container) return;
  // 延迟卸载,避免在同一渲染周期内 unmount 报警告
  const target = container;
  const targetRoot = root;
  container = null;
  root = null;
  setTimeout(() => {
    targetRoot?.unmount();
    target.remove();
  });
}

封装request.ts

在api目录下新建request.ts

ts
import axios, { type AxiosRequestConfig } from "axios";
import { message } from "antd";
import {
  mountLoading,
  unmountLoading,
} from "@/components/common/Loading/loading";

const Axios = axios.create({
  // baseURL: import.meta.env.VITE_BASE_URL, // 设置请求的 base url
  timeout: 20000, // 设置超时时长
});

// 设置 post 请求头
Axios.defaults.headers.post["Content-Type"] =
  "application/x-www-form-urlencoded;charset=UTF-8";

// 当前正在请求的数量
let requestCount = 0;

// 显示 loading
function showLoading() {
  if (requestCount === 0) {
    mountLoading();
  }
  requestCount++;
}

// 隐藏 loading
function hideLoading() {
  requestCount--;
  if (requestCount <= 0) {
    requestCount = 0;
    unmountLoading();
  }
}

// 请求前拦截
Axios.interceptors.request.use(
  (config) => {
    // requestCount 为 0 才创建 loading,避免重复创建
    if (config.headers.isLoading !== false) {
      showLoading();
    }
    return config;
  },
  (err) => {
    if (err.config?.headers?.isLoading !== false) {
      hideLoading();
    }
    return Promise.reject(err);
  },
);

// 返回后拦截
Axios.interceptors.response.use(
  (res) => {
    if (res.config.headers.isLoading !== false) {
      hideLoading();
    }
    return res;
  },
  (err) => {
    if (err.config?.headers?.isLoading !== false) {
      hideLoading();
    }
    if (err.message === "Network Error") {
      message.warning("网络连接异常!");
    }
    if (err.code === "ECONNABORTED") {
      message.warning("请求超时,请重试");
    }
    return Promise.reject(err);
  },
);

// GET 请求
export function get<T = unknown>(
  url: string,
  params?: object,
  config?: AxiosRequestConfig,
) {
  return Axios.get<T>(url, { params, ...config }).then((res) => res.data);
}

// POST 请求
export function post<T = unknown>(
  url: string,
  data?: object,
  config?: AxiosRequestConfig,
) {
  return Axios.post<T>(url, data, config).then((res) => res.data);
}

export default Axios;