vue+ts下對axios的簡單封裝

雖然vue中axios的使用已經(jīng)十分方便,但是實際我們的日常操作中可能為了接口的規(guī)則一致,來創(chuàng)建一個統(tǒng)一管理的全局方法達到簡化操作.而且在實際接口對接中,我們大多都需要對請求和響應進行攔截來進行token以及回調狀態(tài)碼的處理.那么我基于自己的需求簡單分裝了一下.(之前很少接觸vue,主要用的ng和react,這次新項目想用vue來弄,熟悉一下vue的一些新特性和方法,有啥不對的,歡迎大家批評指正)

前提: 熟悉前端ts, node等等.

1. 安裝axios

npm install axios 

2. 攔截器及全局方法編寫

一個http.ts文件進行自己http邏輯的封裝,為了代碼分離,我同時創(chuàng)建interceptors.ts文件進行攔截器邏輯,放在一起也行.

interceptors.ts(攔截器,進行請求和響應攔截并進行部分邏輯處理)

   import axios from 'axios';
   import {message} from 'ant-design-vue';  // 這是我引入的antd的組件庫,為了方便彈出吐司
   
   export class Interceptors {
       public instance: any;
   
       constructor() {
           // 創(chuàng)建axios實例
           this.instance = axios.create({timeout: 1000 * 12});
           // 初始化攔截器
           this.initInterceptors();
       }
       
       // 為了讓http.ts中獲取初始化好的axios實例
       public getInterceptors() {
           return this.instance;
       }
   
   
       // 初始化攔截器
       public initInterceptors() {
           // 設置post請求頭
           this.instance.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
           /**
            * 請求攔截器
            * 每次請求前,如果存在token則在請求頭中攜帶token
            */
           this.instance.interceptors.request.use(
               (config) => {
                   // 登錄流程控制中,根據(jù)本地是否存在token判斷用戶的登錄情況
                   // 但是即使token存在悬槽,也有可能token是過期的循帐,所以在每次的請求頭中攜帶token
                   // 后臺根據(jù)攜帶的token判斷用戶的登錄情況,并返回給我們對應的狀態(tài)碼
                   if (config.headers.isJwt) {
                       const token = localStorage.getItem('id_token');
                       if (token) {
                           config.headers.Authorization = 'Bearer ' + token;
                       }
                   }
                   return config;
               },
               (error) => {
                   console.log(error);
               },
           );
   
   
           // 響應攔截器
           this.instance.interceptors.response.use(
               // 請求成功
               (res) => {
                   if (res.headers.authorization) {
                       localStorage.setItem('id_token', res.headers.authorization);
                   } else {
                       if (res.data && res.data.token) {
                           localStorage.setItem('id_token', res.data.token);
                       }
                   }
   
                   if (res.status === 200) {
                       return Promise.resolve(res.data);
                   } else {
                       this.errorHandle(res);
                       return Promise.reject(res.data);
                   }
               },
               // 請求失敗
               (error) => {
                   const {response} = error;
                   if (response) {
                       // 請求已發(fā)出惠遏,但是不在2xx的范圍
                       this.errorHandle(response);
                       return Promise.reject(response.data);
                   } else {
                       // 處理斷網(wǎng)的情況
                       // eg:請求超時或斷網(wǎng)時砾跃,更新state的network狀態(tài)
                       // network狀態(tài)在app.vue中控制著一個全局的斷網(wǎng)提示組件的顯示隱藏
                       // 關于斷網(wǎng)組件中的刷新重新獲取數(shù)據(jù),會在斷網(wǎng)組件中說明
                       message.warn('網(wǎng)絡連接異常,請稍后再試!');
                   }
               });
       }
   
   
       /**
        * http握手錯誤
        * @param res  響應回調,根據(jù)不同響應進行不同操作
        */
       private errorHandle(res: any) {
           // 狀態(tài)碼判斷
           switch (res.status) {
               case 401:
                   break;
               case 403:
                   break;
               case 404:
                   message.warn('請求的資源不存在');
                   break;
               default:
                   message.warn('連接錯誤');
           }
       }
   }

http.ts(http封裝,自己根據(jù)實際情況處理)

/**
 * @author  keiferju
 * @time    2019-08-29 12:57
 * @title   http請求封裝
 * @desc
 *
 */
import {Interceptors} from '@/service/interceptors';
import {message, Modal} from 'ant-design-vue';   // 彈吐司
import router from '../router';

export class HttpService {
    public axios: any;
    public modal: any;

    constructor() {
            // 獲取axios實例
        this.axios = new Interceptors().getInterceptors();
    }


    /**
     * get請求
     * @param params  參數(shù)
     * @param jwt   是否token校驗
     * @param modulename    模塊
     * @param operation     接口
     * @param flag          標記
     * @param verson       版本,默認1.0.0
     * @param service      服務,默認services
     */
    public getData(params: object, jwt: boolean, modulename: string, operation: string,
                   flag: string, verson = '1.0.0', service = 'services') {

        const url = service + '/' + verson + '/' + modulename + '/' + operation;
        const body = {
            parameter: {
                data: params,
                tag: flag,
            },
        };

        return new Promise((resolve, reject) => {
            this.axios.get(url, {
                params: body,
                headers: {isJwt: jwt},
            }).then((res) => {
                this.resultHandle(res, resolve);
            }).catch((err) => {
                reject(err.message);
            });
        });

    }


    /**
     * post請求
     * @param params  參數(shù)
     * @param jwt   是否token校驗
     * @param modulename    模塊
     * @param operation     接口
     * @param flag          標記
     * @param verson       版本,默認1.0.0
     * @param service      服務,默認services
     */
    public postData(params: object, jwt: boolean, modulename: string, operation: string,
                    flag: string, verson = '1.0.0', service = 'services') {
        const url = service + '/' + verson + '/' + modulename + '/' + operation;
        const body = {
            data: params,
            tag: flag,
        };
        return new Promise((resolve, reject) => {
            this.axios.post(url, body, {
                headers: {isJwt: jwt},
            }).then((res) => {
                this.resultHandle(res, resolve);
            }).catch((err) => {
                reject(err.message);
            });
        });

    }


    /**
     *
     * @param res
     * @param resolve
     */
    public resultHandle(res: any, resolve) {
        if (res.status > 0) {
            resolve(res.data);
        } else {
            this.errorHandle(res);
        }
    }


    /**
     * 服務端狀態(tài)處理,例如中斷性異常,退出異常等等(與攔截器http握手狀態(tài)注意區(qū)分,一般都能分清楚吧)
     * @param res
     */
    public errorHandle(res: any) {
        message.warn(res.msg);  // 統(tǒng)一談服務端提示,我們提示統(tǒng)一由服務端提供
        // 狀態(tài)碼判斷
        switch (res.status) {
            case -102: 
                 break;
            case -152:
                break;
            default:
            // console.log(other);
        }
    }

}

3. 掛載

我們定義好攔截器,那么就得把他掛載全局,能讓我們方便使用.

main.ts

import Vue from 'vue';
import App from './App.vue';
import HighchartsVue from 'highcharts-vue';

Vue.config.productionTip = false;

Vue.prototype.$httpService = new HttpService();  // 掛載服務

new Vue({
    router,
    render: (h) => h(App),
}).$mount('#app');

4. ts橋連(也不知道怎么稱呼,自己從ng時就一直這么稱呼)

行完上一步一定會發(fā)現(xiàn)報錯啊,$httpService是個啥,不存在啊,這是因為ts的特性導致.

main.ts的同級目錄創(chuàng)建一個xx.d.ts文件.

    import {HttpService} from './service/http';
   
declare module 'vue/types/vue' {
    interface Vue {
        $httpService: HttpService;
    }
}

5. 使用

在其它組件中使用,直接用this調用,不用再去引用,但是小心在某個this指向變了的回調中使用時找不到,至于怎么怎么解決應該都懂.

this.$httpService.postData({}, true, 'execute', 'xxx', 'tag').then((result) => {
             // doing            
}, (error) => {
     console.log(error);
});

最后:這是在ts下的封裝,js的話更簡單點,甚至應該會更簡單點(會少一些步驟,網(wǎng)上教程應該很多).掛載http工具的方式平時也適合我們定義全局工具類或者服務.

歡迎訪問我的博客

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末节吮,一起剝皮案震驚了整個濱河市抽高,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌透绩,老刑警劉巖翘骂,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件壁熄,死亡現(xiàn)場離奇詭異,居然都是意外死亡碳竟,警方通過查閱死者的電腦和手機草丧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來莹桅,“玉大人昌执,你說我怎么就攤上這事≌┢茫” “怎么了懂拾?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铐达。 經(jīng)常有香客問我岖赋,道長,這世上最難降的妖魔是什么娶桦? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任贾节,我火速辦了婚禮,結果婚禮上衷畦,老公的妹妹穿的比我還像新娘栗涂。我一直安慰自己,他們只是感情好祈争,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布斤程。 她就那樣靜靜地躺著,像睡著了一般菩混。 火紅的嫁衣襯著肌膚如雪忿墅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天沮峡,我揣著相機與錄音疚脐,去河邊找鬼。 笑死邢疙,一個胖子當著我的面吹牛棍弄,可吹牛的內容都是我干的。 我是一名探鬼主播疟游,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼呼畸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了颁虐?” 一聲冷哼從身側響起蛮原,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎另绩,沒想到半個月后儒陨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體花嘶,經(jīng)...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年框全,在試婚紗的時候發(fā)現(xiàn)自己被綠了察绷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡津辩,死狀恐怖拆撼,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情喘沿,我是刑警寧澤闸度,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站蚜印,受9級特大地震影響莺禁,放射性物質發(fā)生泄漏。R本人自食惡果不足惜窄赋,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一哟冬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忆绰,春花似錦浩峡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至稚茅,卻和暖如春纸淮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背亚享。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工咽块, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人欺税。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓糜芳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親魄衅。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容