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发起数据请求,此时会遇到如下两个问题:
- 每个组件中都需要导入axios(代码臃肿)
- 每次发请求都需要填写完整的请求路径(不利于后期的维护)
全局配置
在main.js入口文件中,通过 app.config.globalProperties
全局挂载axios
//为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并配置基本地址。
import axios from 'axios';
let service = axios.create({
baseURL: 'http://localhost:3000/',
timeout: 3000,
});
export default service;
在 api.js
添加需要用到axios请求的接口函数:
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
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
中配置:
/* 环境配置文件
开发环境 测试环境 线上环境 */
// 当前的环境
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
中存放模拟的数据。
深度封装需求看项目操作,不做多余解释。