Vue3.x中axios的全局配置与封装

2022-11-14 17:40:34 浏览数 (1)

axios在vue中使用,如果不封装的请求写法是如下这样:

代码语言:javascript复制
//先导入axios
import axios from 'axios';

//然后再使用
onMounted(async () => {
  axios.get('http://localhost:3000/banner?type=2').then((res) => {
    console.log(res);
    state.images = res.data.banners;
    console.log(state.images);
  });
});

但是在实际项目开发中,几乎每个组件都会用到axios发起数据请求,此时会遇到如下两个问题:

  1. 每个组件中都需要导入axios(代码臃肿)
  2. 每次发请求都需要填写完整的请求路径(不利于后期的维护)

全局配置

在main.js入口文件中,通过 app.config.globalProperties全局挂载axios

代码语言:javascript复制
//为axios配置请求的根路径
axios.defaults.baseURL='http://api.com'

//将axios挂载为app的全局自定义属性之后
//每个组件可以通过this直接访问到全局挂载的自定义属性
app.config.globalProperties.$http = axios

在组件中发起axios请求:

代码语言:javascript复制
this.$http.get('/users')

简单封装axios

先看目录结构:

创建一个api目录,下面包含index.js和api.js

index.js中导入axios并配置基本地址。

代码语言:javascript复制
import axios from 'axios';
let service = axios.create({
  baseURL: 'http://localhost:3000/',
  timeout: 3000,
});
export default service;

api.js添加需要用到axios请求的接口函数:

代码语言:javascript复制
import service from '.';

// 首页轮播图
export function getBanner() {
  return service({
    method: 'GEt',
    url: '/banner?type=2',
  });
}

在需要请求接口的组件中导入该方法并直接调用该函数发起axios请求:

代码语言:javascript复制
import { getBanner } from '@/api/api.js';

onMounted(async () => {
  let res = await getBanner();
  console.log(res);
  state.images = res.data.banners;
});

深度封装

api>request.js:封装的核心,类简单封装的 index.js

代码语言:javascript复制
import axios from 'axios';
import config from '../config';
import { ElMessage } from 'element-plus';

const NETWORK_ERROR = '网络请求异常,请稍后重试!';
// 创建axios实例对象
const service = axios.create({
  baseURL: config.baseApi,
});

// 在请求之前
service.interceptors.request.use((req) => {
  // 可以自定义header
  // jwt-token认证时候用到
  return req;
});

// 在请求之后
service.interceptors.response.use((res) => {
  // console.log(res.data);
  const { code, data, msg } = res.data;
  //   根据后端协商 视情况而定
  if (code == 200) {
    return data;
  } else if (code == 999) {
    ElMessage.error('网络请求失败,请稍后再试!');
  } else {
    // 网络请求错误提示
    ElMessage.error(msg || NETWORK_ERROR);
    return Promise.reject(msg || NETWORK_ERROR);
  }
});

// 封装的核心函数
function request(options) {
  options.method = options.method || 'get';
  if (options.method.toLowerCase() == 'get') {
    options.params = options.data;
  }
  //对mock的处理
  let isMock = config.isMock;
  if (typeof options.mock !== 'undefined') {
    isMock = options.mock;
  }
  // 对线上环境做处理
  if (config.env == 'prod') {
    // 不给你用到mock的机会
    service.defaults.baseURL = config.baseApi;
  } else {
    service.defaults.baseURL = isMock ? config.mockApi : config.baseApi;
  }
  return service(options);
}

export default request;

但是其中的 BaseUrl信息由 config>index.js中配置:

代码语言:javascript复制
/* 环境配置文件
开发环境 测试环境 线上环境 */

// 当前的环境
const env = import.meta.env.MODE || 'prod';

const EnvConfig = {
  development: {
    baseApi: '/api',
    mockApi: 'https://www.fastmock.site/mock/',
  },
  test: {
    baseApi: '//test.future.com/api',
    mockApi: 'https://www.fastmock.site/mock/',
  },
  pro: {
    baseApi: '///future.com/api',
    mockApi: 'https://www.fastmock.site/mock/',
  },
};

export default {
  env,
  // mock的总开关
  mock: true,
  ...EnvConfig[env],
};

api.js:整个项目的api配置

代码语言:javascript复制
/*
 * 整个项目api的管理
 */
import request from './request';
export default {
  getMenu(params) {
    return request({
      url: '/permission/getMenu',
      method: 'post',
      mock: false,
      data: params,
    });
  },
  getGoodsData() {
    return request({
      url: '/goods/goodsData',
      method: 'get',
       // 如果是true就使用的模拟线上的数据
      mock: true,
    });
  },
};

mock.js拦截数据,mockData中存放模拟的数据。

深度封装需求看项目操作,不做多余解释。

0 人点赞