vue3 axios全局配置封装

13,988 阅读4分钟

Vue项目结构

image.png image.png

配置axios

1. axios 简介

  • Axios 是一个基于 promise 的 HTTP 库。

引入axios

npm install axios
// yarn add axios

基础使用,引入axios

// src/utils/net.js

import axios from 'axios' 
const service = axios.create({ 
    // 配置
})

2. 封装的目的和需求是什么?

  1. 全局添加api默认配置(包括请求头,请求错误处理)

  2. 减少调用次数,方便使用

  3. 特殊请求可配置

基础配置

import axios from 'axios';

const instance = axios.create({
  baseURL: process.env.VUE_APP_API_BASE, // 域名配置
});

// .env.staging 文件 测试环境变量配置

NODE_ENV=production
VUE_APP_ENV=staging
VUE_APP_API_BASE=http://www.xxx.com 替换为自己的测试环境域名

// .env.production 文件 生产环境变量配置

VUE_APP_ENV=production
VUE_APP_API_BASE=https://www.xxx.com 替换为自己的生产环境域名

配置公共默认请求头

import axios from 'axios';

const Api = axios.create({
  baseURL: process.env.VUE_APP_API_BASE, // 域名配置,可添加变量配置文件定义
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
  },
  withCredentials: true, // 跨域请求时是否需要使用凭证
  timeout: 30000, // 请求超时时间
});

// 错误处理函数
// 成功处理函数

到这里,我们已经对axios进行了简单的配置,接下来我们来了解响应结构。

响应结构介绍

{   // `data` 由服务器提供的响应   
    data: {},   
     // `status` 来自服务器响应的 HTTP 状态码   
    status: 200,    
    // `statusText` 来自服务器响应的 HTTP 状态信息   
    statusText: 'OK',    
    // `headers` 服务器响应的头   
    headers: {},    
     // `config` 是为请求提供的配置信息   
    config: {},  
    // 'request'   // `request` is the request that generated this response   // It is the last ClientRequest instance in node.js (in redirects)   // and an XMLHttpRequest instance the browser   
    request: {} 
}

成功/错误拦截处理

在了解了相应结构体之后,我们可以通过then拿到状态在2xx以内的响应体,而catch则可以拿到除了状态在2xx以外的响应体。那么我们可以做一个全局的成功/错误处理拦截器。

import axios, { AxiosRequestConfig, AxiosResponse } from "axios";

const Api = axios.create({
  baseURL: process.env.VUE_APP_API_BASE, // 域名配置,可添加变量配置文件定义
  headers: {
    "Content-Type": "application/x-www-form-urlencoded;charset=utf-8",
  },
  withCredentials: true, // 跨域请求时是否需要使用凭证
  timeout: 30000, // 请求超时时间
});

// 错误处理函数
function errorHandle(response: AxiosResponse) {
  switch (response.status) {
    case 400:
      // 处理错误信息,例如抛出错误信息提示,或者跳转页面等处理方式。
      // return Promise.resolve(error)
      break;
    case 401:
      //
      break;
    case 404:
      //
      break;
    // ...
    default:
      throw new Error("未知错误");
  }
}
// 成功处理函数

function successHandle(response: AxiosResponse) {
  switch (response.status) {
    case 200:
      //
      return response.data;
    // ....
    default:
      return;
  }
}
// 请求拦截器
Api.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    return config;
  },
  (error) => {
    // 错误抛到业务代码
    error.data = {};
    error.data.msg = "服务器异常";
    return Promise.resolve(error);
  }
);

Api.interceptors.response.use(
  (response: AxiosResponse) => {
    successHandle(response);
  },
  (err) => {
    errorHandle(err);
  }
);

export default Api;


对于get、post

看了掘金里其他人对axios的get和post等方法进行了封装,这个完全看业务需求,看怎么封装的,比如有的业务需要额外夹带参数,每次调用的时候要对参数进行处理,这样的就可以简单封装一下,相当于添加一个基础配置,又或者测试或者产品就是要求一定时间内重复的请求不能出现多个,这种情况下可以在全局设置防止重复触发啥的,我觉得是完全没问题的,毕竟我们使用axios是基于业务灵活使用,不过在封装的过程中,我们应该注意的是,我们应该尽量保持 axios 原有的使用方式,即传参和返回格式基本保持一致,不要做成阉割版

将请求方式挂载至全局

封装好axios之后,却发现每次使用都要从文件引入,一份多余的操作都不想?那我们可以把它安排到全局!

// main.js vue3
import { createApp } from "vue";
import App from "./App.vue";
import "./registerServiceWorker";
import router from "./router";
import store from "./store";
import Api from "./utils/net"; // 主要是这里,引入配置好的Api

const app = createApp(App);
app.config.globalProperties.$request = Api; 方法挂载到全局
app.use(store).use(router).mount("#app");

使用方式

<template>
  <div>
    <h1 @click="onClick">{{ conts }}</h1>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref, getCurrentInstance } from "vue";
export default defineComponent({
  setup() {
    const conts = ref("我是子组件");
    const instance: any = getCurrentInstance();
    const onClick = () => {
      instance.proxy.$request("xxx").then()
    };
    return { conts, onClick };
  },
});
</script>

Api 安排思考

无论是需求开发还是排查bug,我们经常要在全局中搜索某个url或者调用某个api,我想,我们把所有api维护在一个requestUrl的对象里会不会好一点呢?这样前端既不用重复写,有需要排查问题的时候也方便查询,这个requestUrl我们也可以稍作处理,让它分模块管理,然后再把这个对象注册到全局(也许是一个大json,也可以不挂载到全局,按需引入),这样是否会使得api path更加清晰呢?

// requestUrl.ts
export default {
    userInfo: '/user/info'
    XXX: XXX
}

下一篇:vue3和vue2对比