VUE中使用AXIOS包装API代理
0. 背景
在VUE开发过程,与后端接口交互时,可以简单几句代码就剋调用后端POST或者GET请求.
实际效果就是,前端定义一个对象- {
- getPageList: 'GET /pagelist',
- commitData: 'POST /savedata',
- getDetail: 'GET /detail/{id}',
- }
复制代码 然后在业务代码中就可以调用getPageList方法,实际效果就是发送一个GET请求,请求地址为/pagelist
常用场景如下:
- api.getPageList("gameName=地心侠士&gameType=小游戏') 会转换成GET请求,参数在URL上 /pagelist?gameName=地心侠士&gameType=小游戏
- api.commitData({gameName:"地心侠士",gameType:"小游戏"}) 会转换成POST请求,参数通过JOSN提交 /savedata
- api.getDetail({id:1}) 会转换成GET请求,参数在URL上 /detail/1
1. 整合全局axios配置
整合axios主要是配置一些全局的请求,响应,以及请求头,请求超时配置等.全局配置代码request.js如下:- import axios from 'axios';
- import loading from './loading';
- const ENV = import.meta.env;
- const { VITE_GLOB_API_URL } = ENV;
- let req = axios.create({
- baseURL: VITE_GLOB_API_URL || '',
- timeout: 30000,
- params: {'g.type': '1'},
- headers:{'g.type': '1'},
- });
- // 请求拦截 公众号 小满小慢
- req.interceptors.request.use((cfg) => {
- loading.showLoading();
- return cfg;
- });
- // 响应拦截 公众号 小满小慢
- req.interceptors.response.use(
- (resp) => {
- loading.hideLoading();
- if (resp.data.code && resp.data.code != '0') {
- // 全局拦截错误信息
- loading.showError(resp.data.message);
- return Promise.reject(resp.data);
- }
- return resp;
- },(error) => {
- loading.hideLoading();
- if (error.response && error.response.data) {
- loading.showError(error.response.data.message);
- }
- return Promise.reject(error);
- },
- );
- export default {
- request: req.request,
- };
复制代码 2. 创建API请求包装器
请求包装器主要有以下作用
实际效果可以把 GET /pagelist 暴露成一个可以调用的方法
,创建API请求包装器apiconvert.js如下:- import req from './request.js';
- export function convertApi(apis) {
- const ENV = import.meta.env;
- const { VITE_GLOB_API_URL } = ENV;
- const api = {};
- for (const key in apis) {
- const apiInfos = apis[key].split(' ');
- const [method, apiUrl] = apiInfos;
- let base = VITE_GLOB_API_URL;
- if (key == 'ajax') base = '/';
- api[key] = (data) => {
- return new Promise((resolve, reject) => {
- let targetUrl = apiUrl;
- if (method === 'GET' && data && typeof data === 'string') {
- // get请求参数处理 公众号 小满小慢
- data = encodeURI(data);
- const index = targetUrl.indexOf('?');
- if (index === -1) {
- data = `?${data}`;
- }
- targetUrl = `${targetUrl}${data}`;
- data = null;
- }
- if (/{\w+}/.test(targetUrl)) {
- targetUrl = targetUrl.replace(/{(\w+)}/gi, function (match, p) {
- return data[p] || '0';
- });
- console.log(`change url:${targetUrl}`);
- }
- req.request({ method: method, url: targetUrl, data: data,baseURL: base})
- .then((res) => resolve(res.data))
- .catch((error) => {
- reject(error);
- });
- });
- };
- }
- return api;
- }
- // 暴露一个通用接口
- const api = convertApi({
- ajax: 'GET /commonDataProc',
- });
- export default api;
复制代码 3. 使用API请求包装器
实际的业务接口可以通过键值对的方式配置,然后通过convertApi方法进行转换,转换后的接口可以调用.
如下:
- 'GET /pagelist'
- 'POST /savedata'
实际业务接口biz_api.js 定义如下- import commapi, { convertApi } from '@/assets/js/apiconvert';
- const api = convertApi({
- // 这里可以扩展业务接口
- getPageList: 'GET /pagelist',
- });
- // 合并通用接口
- Object.assign(api, commapi);
- export default api;
复制代码 4. 使用业务接口
实际业务代码中,通过import api from '@/assets/js/biz_api'引入业务接口,然后调用业务接口即可.- import api from './biz_api.js'
- const data = ref([]);
- const loadingStatus = ref(true);
- async function getPages() {
- const res = await api.getPageList();
- let arr = [];
- for (let i in res) {
- arr.push(res[i]);
- }
- data.value = arr;
- loadingStatus.value = false;
- }
- onMounted(() => {
- getPages()
- });
复制代码 5. 总结
通过以上封装后,前端调用后端的API清晰明了.api定义在单独的文件,也可以自由组合. 从设计上来说,主要使用了两层代理转换.
所有还是印证那句话,一层代理解决不了问题,那就再加一层.
以上仅为个人项目落地总结,若有更优雅的方式,欢迎告知.微信公众号:小满小慢 私信或者直接留言都可以.
原文地址 https://mp.weixin.qq.com/s/aqHVyq_I3m0QcSbKDqCxuQ
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |