vite+vue3项目从0到1搭建(3)---请求封装

github仓库地址: github.com/Liangjiahon...

  • 安装 axios
shell 复制代码
 pnpm i axios
  • 在根目录下新建 service 文件夹,进行 axios 封装

目录结构如下

  • modules: 区分每个模块下的请求,如登录退出的房 auth.js 中,首页相关请求放 home.js
  • index: 用于同一暴露各个模块的请求
  • request: 二次封装的请求类

实现一个 Request 类,对 axios 的二次封装

  • 初始化请求相关的信息
javascript 复制代码
 // request.js
 import axios from "axios";
 ​
 class Request {
   constructor(baseURL, timeout) {
     this.instance = axios.create({
       baseURL,
       timeout,
       // 添加默认的Content-Type
       headers: { "Content-Type": "application/x-www-form-urlencoded" }
     });
 ​
     this.showLoading = false; // 用于控制loading
     this.loadingInstance = null; // loading实例
     this.interceptorsSetup(); // 建立请求拦截和响应拦截
   }
 }
 ​
 const { VITE_BASE_URL } = import.meta.env;
 const request = new Request(VITE_BASE_URL, 2000);
 ​
 export default request;
  • 实现请求和响应拦截
javascript 复制代码
 import router from "@/router";
 import useLoading from "@/hooks/useLoading";
 class Request {
   ...
    
   interceptorsSetup() {
     this.instance.interceptors.request.use(
       (config) => {
         // 判断请求时有没有传入loading
         this.showLoading = config.showLoading ?? this.showLoading;
         // 有传入loading就显示
         if (this.showLoading) {
           const { loadingInstance } = useLoading();
           this.loadingInstance = loadingInstance;
         }
         // 有token则带上到请求头中
         const token = localStorage.getItem("token") || "";
         if (token) {
           config.headers && (config.headers["token"] = token);
         }
         return config;
       },
       (err) => {
         console.error("网络请求出错", err);
         this.loadingInstance?.close();
         return err;
       }
     );
 ​
     this.instance.interceptors.response.use(
       (response) => {
         // 请求完成,关闭loading
         this.loadingInstance?.close();
         const { code } = response.data;
 ​
         // 判断token是否过期,过期则跳转到登录页面并清除token
         if (code === 401) {
           localStorage.removeItem("token");
           router.replace("/login");
           return Promise.reject(response.data);
         }
         return response;
       },
       (err) => {
         console.log("请求响应报错", err);
         this.loadingInstance?.close();
         return err;
       }
     );
   }
 }
  • 结合 elementPlus 实现一个loading hook
  • 在根目录下新建 hooks 目录,用于存放自定义的 hooks
javascript 复制代码
 // hooks/useLoading.js
 import { ElLoading } from "element-plus";
 ​
 const useLoadingHook = (text = "loading") => {
   const loadingInstance = ElLoading.service({
     text,
     background: "rgba(0, 0, 0, 0.7)"
   });
 ​
   const closeLoading = () => loadingInstance.close();
   return { loadingInstance, closeLoading };
 };
 ​
 export default useLoadingHook;
  • 实现基础请求方法,通过 Promise 返回请求结果
javascript 复制代码
 request(config) {
   return new Promise((resolve, reject) => {
     this.instance
       .request(config)
       .then((res) => {
         resolve(res.data);
       })
       .catch((err) => {
         console.log("request err:", err);
         reject(err);
       });
   });
 }
  • 封装 getpost 请求
javascript 复制代码
 get(config) {
   return this.request({ ...config, method: "get" });
 }
 ​
 // 以params格式传参使用
 post(config) {
   return this.request({ ...config, method: "post" });
 }
 ​
 // 以Json格式传参使用
 postJson(config) {
   return this.request({
     ...config,
     method: "post",
     headers: { "Content-Type": "application/json" }
   });
 }
  • 将封装的 request 实例暴露
javascript 复制代码
 const { VITE_BASE_URL } = import.meta.env; // 根据环境加载不同的请求地址
 const request = new Request(VITE_BASE_URL, 2000);
 export default request;

基于封装的 request 实例,实现登录接口函数

  • 按照对应接口,将请求的函数写入到对应的模块中
javascript 复制代码
 // service/modules/auth.js
 import request from "../request";
 ​
 export const login = (params = {}) => {
   return request.post({ url: "/login", params, showLoading: true });
 };
 ​
  • 通过 index 统一暴露
javascript 复制代码
 export * from "./modules/home";
 export * from "./modules/auth";

使用定义好的请求函数

javascript 复制代码
 import { login } from "@/service";
 ​
 login().then((res) => {
   console.log(res);
 });
相关推荐
开开心心就好3 小时前
批量提取PDF中的图片,直接导出原图
前端·javascript·支持向量机·智能手机·pdf·html·启发式算法
Setsuna_F_Seiei5 小时前
前端转型 Agent 开发 05 之 Agent Hooks 与 Checkpointer(让 Agent 从全自动转变人为可掌控)
前端·agent·ai编程
百万蹄蹄向前冲7 小时前
风扇转了一晚上MVP专家团翻车事故
前端·人工智能
默_笙7 小时前
🏛 给 AI 配一间办公室:Harness Engineering 六大模块与它的实现
前端·javascript
linux_cfan8 小时前
videojs v10 源代码系列解读:14 · 谓词守卫:在运行时安全地调用能力
前端·javascript·音视频
kyriewen8 小时前
我扒了 10,221 条 JD:腾讯技术岗 75% 在要 AI
前端·人工智能·ai编程
郑州光合科技余经理9 小时前
同城外卖小程序开发:下单成功后,后台导出能不能对上用户端状态
开发语言·前端·git·后端·uni-app·php·ai编程
+VX:Fegn089510 小时前
计算机毕业设计|基于springboot + vue旅游管理系统(源码+数据库+文档)
java·开发语言·vue.js·spring boot·课程设计
雪芽蓝域zzs10 小时前
第 7 章:双 Y 轴组合图(柱状 + 折线,看板高频场景)
vue.js·echars
IT_陈寒10 小时前
Vue的响应式让我熬到凌晨三点,原来漏了这个小细节
前端·人工智能·后端