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);
 });
相关推荐
IT_陈寒35 分钟前
Python+AI实战:用LangChain构建智能问答系统的5个核心技巧
前端·人工智能·后端
袁煦丞1 小时前
MoneyPrinterTurbo一键生成短视频:cpolar内网穿透实验室第644个成功挑战
前端·程序员·远程工作
代码小学僧1 小时前
让 AI 真正帮你开发:前端 MCP 实用技巧分享
前端
晴殇i1 小时前
前端鉴权新时代:告别 localStorage,拥抱更安全的 JWT 存储方案
前端·javascript·面试
Json____1 小时前
使用node Express 框架框架开发一个前后端分离的二手交易平台项目。
java·前端·express
since �1 小时前
前端转Java,从0到1学习教程
java·前端·学习
小奋斗1 小时前
面试官:[1] == '1'和[1] == 1结果是什么?
前端·面试
萌萌哒草头将军1 小时前
尤雨溪宣布 oxfmt 即将发布!比 Prettier 快45倍 🚀🚀🚀
前端·webpack·vite
weixin_405023371 小时前
webpack 学习
前端·学习·webpack
云中雾丽1 小时前
flutter中 Future 详细介绍
前端