前言
前端系统开发中,由于功能的复杂性后台的数据接口会很多,如果每个请求都写在相应的页面中维护起来特别繁琐,所以就需要一个统一管理API的地方,已达到快速定位,这时候就需要请求与API模块相关联,以实现相应的操作。
对axios库进行基本封装
项目中使用的ajax请求库是axios,关于axios配置及拦截就不在这复述,网上例子很多,直接上二次封装的代码
import API from './api'; //存放API的模块import axios from '@/config/axios' import {Message} from 'element-ui'import {merge,path,isArray} from '@/assets/js/tool' //自定义封装的辅助函数工具const placeholder=/\{(\w+)\}?/gi; //占位符export class Fetch { constructor(baseURL){ this.baseURL=baseURL || '/api'; this.headers=axios.defaults.headers; } //这里是提交请求的入口,返回一个promiss commit(url,payload,showMes){ const req= path(isArray(url)?url:[url],API); const isShowMes=arguments.length===3 && Array.prototype.slice.call(arguments).pop(); const urlPath= payload && payload.path?this.buildPath(req.url,payload.path):req.url; return new Promise((resolve,reject)=>{ axios({ url:this.baseURL.concat(urlPath), method:req.method.toLowerCase(), headers:this.headers, data:payload.data || null, params:payload.params || null, timeout:5000 }).then(res=>{ const isError=this.creatErrorMes(res.data); if(isError){ Message({message:res.data.msg,type:'error'}); }else{ isShowMes ? Message(this.makeMessage(res.data)):false; resolve(res.data); } }) }) } //这里只是简单的用了一下axios的header setHeader(config){ this.headers=merge(this.headers,config) } //解析类似 /api/page/2这样动态参数的问题,用正则去匹配我们的占位符,把真实数据放进去 buildPath(url,path){ if(!path)return url; return url.replace(placeholder,function ($1,$2) { return $2=encodeURIComponent(path[$2]); }); } // 解析对象为params字符串,以便放入query中,考虑axios请求封装了get的参数,这里没用到 buildUrlParams(url,params){ if(!params)return url; let p=[]; Object.keys(params).forEach(key=>{ p.push(`${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`); }); return url += (url.indexOf('?') === -1 ? '?' : '') + p.join('&'); } // 统一设置前端接受数据或操作接口成功会给出的提示 makeMessage(data){ const mes={ message:data.message || "执行成功", type:'success' }; if(data.data && (!Object.keys(data.data).length || !data.data.length )){ mes.mesasge='暂无数据'; mes.type='warning'; return mes; }; return mes } //创建收集后台代码错误信息并返回,有错误直接返回true creatErrorMes(data){ // 收集后台出错的常见字段 const error=['code','msg'].every(item=>data.hasOwnProperty(item)); if(!Array.isArray(data) && typeof data ==='object' && data!==null && error){ return true; }; return false } }//以插件的形式封装,挂载到Vue中export function plugin(Vue,fetch){ if(plugin.installed){ return }; plugin.installed=true; Vue.fetch=fetch; Object.defineProperties(Vue.prototype, { fetch: { get() { return fetch } }, }) }
接下来在看一下API模块就简单了,可以按照页面或功能分类去管理接口
export default { login:{ url:'/xxxx/token', method:'post', }, user:{ info:{ url:'/xxx/info', method:'get' }, page:{ url:'/xxx/page/{num}' method:'get' } } }
使用方法
项目中使用封装的请求可以这样
Vue.use(plugin,new Fetch());
这里展示的是请求API对象的一级键值
this.fetch.commit('login',{ data:{ username:'xxx', password:'xxx' } }).then(res=>{ //do something })
如果想请求类似接口中user的深层嵌套,可以这样
//这里封装了prop方法以方便获取更深层的对象 this.fetch.commit(['user','info'],{ params:{ id:'56', } },true)// 请求成功后会给出相应的提示 .then(res=>{ //do something })
再来一个参数放在path的
// 执行完以后完整的url为:'/xxx/page/1'this.fetch.commit(['user','page'],{ path:{ num:'1',//这里是占位符相应的字段 }, params:{ .... //附带的参数请求 } }) .then(res=>{ //do something })
结束
基本思路就是这样,其实还有很多可以抽离优化的地方,也有很多设计不满意的,不过现在基本可以满足日常开发,后期会不断优化。
作者:layah
链接:https://www.jianshu.com/p/6e7d92d052c0
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦