找回密码
 立即注册
首页 业界区 安全 VUE中使用AXIOS包装API代理

VUE中使用AXIOS包装API代理

峰邑 1 小时前
VUE中使用AXIOS包装API代理

0. 背景

在VUE开发过程,与后端接口交互时,可以简单几句代码就剋调用后端POST或者GET请求.
实际效果就是,前端定义一个对象
  1. {
  2.   getPageList: 'GET /pagelist',
  3.   commitData: 'POST /savedata',
  4.   getDetail: 'GET /detail/{id}',
  5. }
复制代码
然后在业务代码中就可以调用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如下:
  1. import axios from 'axios';
  2. import loading from './loading';
  3. const ENV = import.meta.env;
  4. const { VITE_GLOB_API_URL } = ENV;
  5. let req = axios.create({
  6.   baseURL: VITE_GLOB_API_URL || '',
  7.   timeout: 30000,
  8.   params: {'g.type': '1'},
  9.   headers:{'g.type': '1'},
  10. });
  11. // 请求拦截 公众号 小满小慢
  12. req.interceptors.request.use((cfg) => {
  13.   loading.showLoading();
  14.   return cfg;
  15. });
  16. // 响应拦截 公众号 小满小慢
  17. req.interceptors.response.use(
  18.   (resp) => {
  19.     loading.hideLoading();
  20.     if (resp.data.code && resp.data.code != '0') {
  21.       // 全局拦截错误信息
  22.       loading.showError(resp.data.message);
  23.       return Promise.reject(resp.data);
  24.     }
  25.     return resp;
  26.   },(error) => {
  27.     loading.hideLoading();
  28.     if (error.response && error.response.data) {
  29.       loading.showError(error.response.data.message);
  30.     }
  31.     return Promise.reject(error);
  32.   },
  33. );
  34. export default {
  35.   request: req.request,
  36. };
复制代码
2. 创建API请求包装器

请求包装器主要有以下作用

  • 请求参数处理
  • 通用接口暴露
实际效果可以把 GET /pagelist 暴露成一个可以调用的方法
,创建API请求包装器apiconvert.js如下:
  1. import req from './request.js';
  2. export function convertApi(apis) {
  3.   const ENV = import.meta.env;
  4.   const { VITE_GLOB_API_URL } = ENV;
  5.   const api = {};
  6.   for (const key in apis) {
  7.     const apiInfos = apis[key].split(' ');
  8.     const [method, apiUrl] = apiInfos;
  9.     let base = VITE_GLOB_API_URL;
  10.     if (key == 'ajax') base = '/';
  11.     api[key] = (data) => {
  12.     return new Promise((resolve, reject) => {
  13.       let targetUrl = apiUrl;
  14.       if (method === 'GET' && data && typeof data === 'string') {
  15.         // get请求参数处理 公众号 小满小慢
  16.         data = encodeURI(data);
  17.         const index = targetUrl.indexOf('?');
  18.         if (index === -1) {
  19.           data = `?${data}`;
  20.         }
  21.         targetUrl = `${targetUrl}${data}`;
  22.         data = null;
  23.       }
  24.       if (/{\w+}/.test(targetUrl)) {
  25.         targetUrl = targetUrl.replace(/{(\w+)}/gi, function (match, p) {
  26.           return data[p] || '0';
  27.         });
  28.         console.log(`change url:${targetUrl}`);
  29.       }
  30.       req.request({ method: method, url: targetUrl, data: data,baseURL: base})
  31.         .then((res) => resolve(res.data))
  32.         .catch((error) => {
  33.           reject(error);
  34.         });
  35.     });
  36.     };
  37.   }
  38.   return api;
  39. }
  40. // 暴露一个通用接口
  41. const api = convertApi({
  42.   ajax: 'GET /commonDataProc',
  43. });
  44. export default api;
复制代码
3. 使用API请求包装器

实际的业务接口可以通过键值对的方式配置,然后通过convertApi方法进行转换,转换后的接口可以调用.
如下:

  • 'GET /pagelist'
  • 'POST /savedata'
实际业务接口biz_api.js 定义如下
  1. import commapi, { convertApi } from '@/assets/js/apiconvert';
  2. const api = convertApi({
  3.   // 这里可以扩展业务接口
  4.   getPageList: 'GET /pagelist',
  5. });
  6. // 合并通用接口
  7. Object.assign(api, commapi);
  8. export default api;
复制代码
4. 使用业务接口

实际业务代码中,通过import api from '@/assets/js/biz_api'引入业务接口,然后调用业务接口即可.
  1. import api from './biz_api.js'
  2. const data = ref([]);
  3. const loadingStatus = ref(true);
  4. async function getPages() {
  5.   const res = await api.getPageList();
  6.   let arr = [];
  7.   for (let i in res) {
  8.     arr.push(res[i]);
  9.   }
  10.   data.value = arr;
  11.   loadingStatus.value = false;
  12. }
  13. onMounted(() => {
  14.   getPages()
  15. });
复制代码
5. 总结

通过以上封装后,前端调用后端的API清晰明了.api定义在单独的文件,也可以自由组合. 从设计上来说,主要使用了两层代理转换.
所有还是印证那句话,一层代理解决不了问题,那就再加一层.
以上仅为个人项目落地总结,若有更优雅的方式,欢迎告知.微信公众号:小满小慢 私信或者直接留言都可以.
原文地址 https://mp.weixin.qq.com/s/aqHVyq_I3m0QcSbKDqCxuQ

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册