美文网首页前端Vue专辑JavaScriptVue.js
axios二次封装及API接口统一管理

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

作者: layah | 来源:发表于2018-08-31 19:31 被阅读2次

    前言


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

    结束


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

    相关文章

      网友评论

        本文标题:axios二次封装及API接口统一管理

        本文链接:https://www.haomeiwen.com/subject/muyewftx.html