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);
 });
相关推荐
家里有只小肥猫8 分钟前
uniApp小程序保存canvas图片
前端·小程序·uni-app
前端大全10 分钟前
Chrome 推出全新的 DOM API,彻底革新 DOM 操作!
前端·chrome
前端小臻38 分钟前
关于css中bfc的理解
前端·css·bfc
白嫖不白嫖1 小时前
网页版的俄罗斯方块
前端·javascript·css
HappyAcmen1 小时前
关于Flutter前端面试题及其答案解析
前端·flutter
顾比魁1 小时前
pikachu之CSRF防御:给你的请求加上“网络身份证”
前端·网络·网络安全·csrf
林的快手1 小时前
CSS文本属性
前端·javascript·css·chrome·node.js·css3·html5
肥肠可耐的西西公主2 小时前
前端(AJAX)学习笔记(CLASS 2):图书管理案例以及图片上传
前端·笔记·学习
大胖丫2 小时前
vue 学习-vite api.js
开发语言·前端·javascript
孙桂月2 小时前
ES6相关操作(2)
前端·javascript·es6