axios二次封裝及API接口統一管理

前言


前端系統開發中,因爲功能的複雜性後臺的數據接口會不少,若是每一個請求都寫在相應的頁面中維護起來特別繁瑣,因此就須要一個統一管理API的地方,已達到快速定位,這時候就須要請求與API模塊相關聯,以實現相應的操做。前端

對axios庫進行基本封裝


項目中使用的ajax請求庫是axios,關於axios配置及攔截就不在這複述,網上例子不少,直接上二次封裝的代碼ios

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模塊就簡單了,能夠按照頁面或功能分類去管理接口ajax

export default {
    login:{
        url:'/xxxx/token',
        method:'post',
    },
    user:{
        info:{
            url:'/xxx/info',
            method:'get'
        },
        page:{
            url:'/xxx/page/{num}'
            method:'get'
        }
    }
}
複製代碼

使用方法


項目中使用封裝的請求能夠這樣element-ui

Vue.use(plugin,new Fetch());
複製代碼

這裏展現的是請求API對象的一級鍵值axios

this.fetch.commit('login',{
        data:{
            username:'xxx',
            password:'xxx'
        }
    }).then(res=>{
        //do something
    })
複製代碼

若是想請求相似接口中user的深層嵌套,能夠這樣api

//這裏封裝了prop方法以方便獲取更深層的對象
 this.fetch.commit(['user','info'],{
        params:{
            id:'56',
        }
    },true)// 請求成功後會給出相應的提示
    .then(res=>{
        //do something
    })
複製代碼

再來一個參數放在path的bash

// 執行完之後完整的url爲:'/xxx/page/1'
this.fetch.commit(['user','page'],{
        path:{
            num:'1',//這裏是佔位符相應的字段
        },
        params:{
            .... //附帶的參數請求 
        }
    })
    .then(res=>{
        //do something
    })
複製代碼

結束


基本思路就是這樣,其實還有不少能夠抽離優化的地方,也有不少設計不滿意的,不過如今基本能夠知足平常開發,後期會不斷優化。函數

相關文章
相關標籤/搜索