axios二次封装及API接口统一管理

前言


前端系统开发中,由于功能的复杂性后台的数据接口会很多,如果每个请求都写在相应的页面中维护起来特别繁琐,所以就需要一个统一管理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
    })
复制代码

结束


基本思路就是这样,其实还有很多可以抽离优化的地方,也有很多设计不满意的,不过现在基本可以满足日常开发,后期会不断优化。

转载于:https://juejin.im/post/5b8924b0f265da437174c50a

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值