Skip to content

axios

axios中文文档|axios中文网 | axios

是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中

安装

npm install axios

使用方法

对 axios 进行二次封装,设置请求拦截和响应拦截,在响应时对于不同的状态码提供不同的 loading,封装 get 和 post 等请求,并且将参数处理成加密的形式

常见用法

本地json文件模拟接口返回值

js
sendRequest() {
    return new Promise((resolve, reject) => {
            let Qurl = `https://${location.host}/xxxx`;
            let methodType = "post"
            if(this.isDevEnv()){
                Qurl = `js/xxx.json`;
                methodType = "get";
            }

            let Qdata = {
                Id: '',
                Key:'',
            };
            axios({
                method:methodType,
                url:Qurl,
                data:Qdata
            }).then(r => {
                if(r.data.code === 0) {
                    console.log("处理有效值")
                    resolve(true)
                } else {
                    // 处理异常返回值
                    if(r.data.code == '-1') {
                        vant.Toast({
                            message: 'xxx',
                            forbidClick: true,
                            duration: 0
                        });
                        resolve(true)
                    } else {
                        // 【接口类型错误】
                        vant.Toast(r.data.msg);
                        reject(r.data.msg)
                    }
                }
            }).catch(err => {
                reject(err)
            })
        })
}
js
isDevEnv() {
    return location.host.includes('localhost') || location.host.startsWith("192.168");
},

工具封装

src/utils/request.ts

ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { ElMessage, ElMessageBox } from 'element-plus';
import { localStorage } from '@/utils/storage';
import useStore from '@/store';


// 创建axios实例
const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  // 请求超时时间:50s
  timeout: 50000,
  headers: { 'Content-Type': 'application/json;charset=utf-8' },
});


// 请求拦截器
service.interceptors.request.use(
  (config: AxiosRequestConfig) => {
    if (!config.headers) {
      throw new Error(
        `Expected 'config' and 'config.headers' not to be undefined`
      );
    }
    const { user } = useStore();
    if (user.token) {
      // 授权认证
      config.headers.Authorization = user.token;
    }
    // 租户ID
    config.headers['TENANT_ID'] = '1'
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);


// 响应拦截器
service.interceptors.response.use(
  (response: AxiosResponse) => {
    const res = response.data;
    const { code, msg } = res;
    if (code === 200) {
      return res;
    } else {
      // token过期
      if (code === -1) {
        ElMessageBox.confirm("您的登录账号已失效,请重新登录", {
          confirmButtonText: "再次登录",
          cancelButtonText: "取消",
          type: "warning"
        }).then(() => {
          // 清除浏览器全部缓存
          localStorage.clear();
          // 跳转登录页
          window.location.href = '/';
          location.reload();
        });
      } else {
        ElMessage({
          message: msg || '系统出错',
          type: 'error',
          duration: 5 * 1000
        });
      }
      return Promise.reject(new Error(msg || 'Error'));
    }
  },
  (error) => {
    const { msg } = error.response.data;
    // 未认证
    if (error.response.status === 401) {
      ElMessageBox.confirm("您的登录账号已失效,请重新登录", {
        confirmButtonText: "再次登录",
        cancelButtonText: "取消",
        type: "warning"
      }).then(() => {
        // 清除浏览器全部缓存
        localStorage.clear();
        // 跳转登录页
        window.location.href = '/';
        location.reload();
      });
    } else {
      ElMessage({
        message: "网络异常,请稍后再试!",
        type: "error",
        duration: 5 * 1000
      });
      return Promise.reject(new Error(msg || 'Error'));
    }
  }
);

// 导出实例
export default service;

api封装

src/api/index.ts

ts
// 拿到所有api
const modulesFiles = import.meta.globEager('./*/*.*');
const modules: any = {};
for (const key in modulesFiles) {
  const moduleName = key.replace(/(.*\/)*([^.]+).*/gi, '$2');
  const value: any = modulesFiles[key];
  if (value.default) {
    // 兼容js
    modules[moduleName] = value.default;
  } else {
    // 兼容ts
    modules[moduleName] = value;
  }
}
// console.log(666, modules);
export default modules;

main.ts

ts
const app = createApp(App);

// 配置全局api
import api from '@/api'
app.config.globalProperties.$api = api;

app.mount('#app')

api调用demo

src/api/system/sys_login.ts

ts
import { Captcha } from '@/types/api/system/login';
import request from '@/utils/request';
import { AxiosPromise } from 'axios';

// 获取验证码
export function getCaptcha(): AxiosPromise<Captcha> {
    return request({
        url: '/captcha?t=' + new Date().getTime().toString(),
        method: 'get',
    });
}

src/types/api/system/login.d.ts

ts
// 验证码类型声明
export interface Captcha {
    img: string;
    uuid: string;
}

src/views/login/index.vue

ts
<template>
    <p>Hello...</p>
</template>
 
<script lang="ts" setup>
import { getCurrentInstance } from 'vue';
// 组件实例
const { proxy }: any = getCurrentInstance();
// 获取验证码
async function handleCaptcha() {
    const res = await proxy.$api.sys_login.getCaptcha()
    console.log('res:', res);
}
handleCaptcha()
</script>

解决跨域问题

js
module.exports = {
  devServer: {
    // ....
    proxy: {
      //配置跨域
      '/api': {
        target: 'https://test.xxx.com', // 接口的域名
        // ws: true, // 是否启用websockets
        changOrigin: true, // 开启代理,在本地创建一个虚拟服务端
        pathRewrite: {
          '^/api': '/'
        }
      }
    }
  }
}

https://blog.csdn.net/GuyYgl/article/details/114692572

https://www.bilibili.com/video/BV15f4y127tM

https://www.jianshu.com/p/12b7ef08bc54

配置proxy跨域

如果你的项目需要配置跨域,你需要打开 vue.config.jsproxy注释 并且配置响应参数

注意:你还需要将 src/config/env.development.js 里的 baseApi 设置成 ‘/'