Vue 中 Axios 的封裝和 API 接口的管理

一. 封裝各模塊作用

  1. 引入
    一般我會在項(xiàng)目的src目錄中,新建一個(gè)request文件夾,然后在里面新建一個(gè)http.js和一個(gè)api.js文件。http.js文件用來封裝我們的axios,api.js用來統(tǒng)一管理我們的接口纲岭。
// 在http.js中引入axios
import axios from 'axios'; // 引入axios
import QS from 'qs'; // 引入qs模塊,用來序列化post類型的數(shù)據(jù)线罕,后面會提到
// vant的toast提示框組件止潮,大家可根據(jù)自己的ui組件更改。
import { Toast } from 'vant'; 

  1. 環(huán)境切換
    我們的項(xiàng)目環(huán)境可能有開發(fā)環(huán)境闻坚、測試環(huán)境和生產(chǎn)環(huán)境沽翔。我們通過node的環(huán)境變量來匹配我們的默認(rèn)的接口url前綴兢孝。axios.defaults.baseURL可以設(shè)置axios的默認(rèn)請求地址就不多說了
if (process.env.NODE_ENV == 'development') {    
    axios.defaults.baseURL = '/api';
} else if (process.env.NODE_ENV == 'debug') {    
    axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {    
    axios.defaults.baseURL = 'http://api.123dailu.com/';
}

  1. 請求頭的默認(rèn)配置
    通過axios.defaults.timeout設(shè)置默認(rèn)的請求超時(shí)時(shí)間窿凤。例如超過了10s,就會告知用戶當(dāng)前請求超時(shí)跨蟹,請刷新等雳殊。 通過設(shè)置 withCredentials: true ,發(fā)送Ajax時(shí)窗轩,Request header中便會帶上 Cookie 信息琳猫。 post請求的時(shí)候雁比,我們需要加上一個(gè)請求頭吠勘,所以可以在這里進(jìn)行一個(gè)默認(rèn)的設(shè)置柴灯,即設(shè)置post的請求頭為application/x-www-form-urlencoded;charset=UTF-8
// 請求超時(shí)時(shí)間
axios.defaults.timeout = 10000;
// 在客戶端axios請求中設(shè)置
axios.defaults.withCredentials = true
// 通過設(shè)置 withCredentials: true ,發(fā)送Ajax時(shí)鞠呈,Request header中便會帶上 Cookie 信息。
// post請求頭
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

  1. 請求攔截器
    我們在發(fā)送請求前可以進(jìn)行一個(gè)請求的攔截,為什么要攔截呢哺呜,我們攔截請求是用來做什么的呢?比如箕戳,有些請求是需要用戶登錄之后才能訪問的某残,或者post請求的時(shí)候,我們需要序列化我們提交的數(shù)據(jù)陵吸。這時(shí)候玻墅,我們可以在請求被發(fā)送之前進(jìn)行一個(gè)攔截,從而進(jìn)行我們想要的操作壮虫。
// 請求攔截器
axios.interceptors.request.use(    
    config => {
        // 每次發(fā)送請求之前判斷是否存在token澳厢,如果存在,則統(tǒng)一在http請求的header都加上token囚似,不用每次請求都手動添加了
        // 即使本地存在token赏酥,也有可能token是過期的,所以在響應(yīng)攔截器中要對返回狀態(tài)進(jìn)行判斷
        const token = store.state.token;        
        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => {        
        return Promise.error(error);    
    }
)

注意:

這里說一下token谆构,一般是在登錄完成之后裸扶,將用戶的token通過localStorage或者cookie存在本地,然后用戶每次在進(jìn)入頁面的時(shí)候(即在main.js中)搬素,會首先從本地存儲中讀取token呵晨,如果token存在說明用戶已經(jīng)登陸過,則更新vuex中的token狀態(tài)熬尺。然后摸屠,在每次請求接口的時(shí)候,都會在請求的header中攜帶token粱哼,后臺人員就可以根據(jù)你攜帶的token來判斷你的登錄是否過期季二,如果沒有攜帶,則說明沒有登錄過揭措。這時(shí)候或許有些小伙伴會有疑問了胯舷,就是每個(gè)請求都攜帶token,那么要是一個(gè)頁面不需要用戶登錄就可以訪問的怎么辦呢绊含?其實(shí)桑嘶,你前端的請求可以攜帶token,但是后臺可以選擇不接收肮洹逃顶!

  1. 響應(yīng)攔截器
    響應(yīng)攔截器很好理解讨便,就是服務(wù)器返回給我們的數(shù)據(jù),我們在拿到之前可以對他進(jìn)行一些處理以政。例如上面的思想:如果后臺返回的狀態(tài)碼是200霸褒,則正常返回?cái)?shù)據(jù),否則的根據(jù)錯(cuò)誤的狀態(tài)碼類型進(jìn)行一些我們需要的錯(cuò)誤盈蛮,其實(shí)這里主要就是進(jìn)行了錯(cuò)誤的統(tǒng)一處理和沒登錄或登錄過期后調(diào)整登錄頁的一個(gè)操作傲霸。
// 響應(yīng)攔截器
axios.interceptors.response.use(    
    response => {        
        if (response.status === 200) {            
            return Promise.resolve(response);        
        } else {            
            return Promise.reject(response);        
        }    
    },
    // 服務(wù)器狀態(tài)碼不是200的情況    
    error => {        
        if (error.response.status) {            
            switch (error.response.status) {                
                // 401: 未登錄                
                // 未登錄則跳轉(zhuǎn)登錄頁面,并攜帶當(dāng)前頁面的路徑                
                // 在登錄成功后返回當(dāng)前頁面眉反,這一步需要在登錄頁操作昙啄。                
                case 401:                    
                    router.replace({                        
                        path: '/login',                        
                        query: { redirect: router.currentRoute.fullPath } 
                    });
                    break;
                // 403 token過期                
                // 登錄過期對用戶進(jìn)行提示                
                // 清除本地token和清空vuex中token對象                
                // 跳轉(zhuǎn)登錄頁面                
                case 403:                     
                    Toast({                        
                        message: '登錄過期,請重新登錄',                        
                        duration: 1000,                        
                        forbidClick: true                    
                    });                    
                    // 清除token                    
                    localStorage.removeItem('token');                    
                    store.commit('loginSuccess', null);                    
                    // 跳轉(zhuǎn)登錄頁面寸五,并將要瀏覽的頁面fullPath傳過去梳凛,登錄成功后跳轉(zhuǎn)需要訪問的頁面
                    setTimeout(() => {                        
                        router.replace({                            
                            path: '/login',                            
                            query: { 
                                redirect: router.currentRoute.fullPath 
                            }                        
                        });                    
                    }, 1000);                    
                    break; 
                // 404請求不存在                
                case 404:                    
                    Toast({                        
                        message: '網(wǎng)絡(luò)請求不存在',                        
                        duration: 1500,                        
                        forbidClick: true                    
                    });                    
                break;                
                // 其他錯(cuò)誤,直接拋出錯(cuò)誤提示                
                default:                    
                    Toast({                        
                        message: error.response.data.message,                        
                        duration: 1500,                        
                        forbidClick: true                    
                    });            
            }            
            return Promise.reject(error.response);        
        }       
    }
);

二. 封裝后代碼

/**axios封裝
 * 請求攔截梳杏、相應(yīng)攔截韧拒、錯(cuò)誤統(tǒng)一處理
 */
import axios from 'axios'; 
import QS from 'qs';
import { Toast } from 'vant';
import store from '../store/index'

// 環(huán)境的切換
if (process.env.NODE_ENV == 'development') {    
    axios.defaults.baseURL = '/api';
} else if (process.env.NODE_ENV == 'debug') {    
    axios.defaults.baseURL = '';
} else if (process.env.NODE_ENV == 'production') {    
    axios.defaults.baseURL = 'http://api.123dailu.com/';
}

// 請求超時(shí)時(shí)間
axios.defaults.timeout = 10000;
// 在客戶端axios請求中設(shè)置
axios.defaults.withCredentials = true
// 通過設(shè)置 withCredentials: true ,發(fā)送Ajax時(shí)十性,Request header中便會帶上 Cookie 信息叛溢。
// post請求頭
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';

// 請求攔截器
axios.interceptors.request.use(    
    config => {
        // 每次發(fā)送請求之前判斷是否存在token,如果存在劲适,則統(tǒng)一在http請求的header都加上token楷掉,不用每次請求都手動添加了
        // 即使本地存在token,也有可能token是過期的霞势,所以在響應(yīng)攔截器中要對返回狀態(tài)進(jìn)行判斷
        const token = store.state.token;        
        token && (config.headers.Authorization = token);        
        return config;    
    },    
    error => {        
        return Promise.error(error);    
    }
)

// 響應(yīng)攔截器
axios.interceptors.response.use(    
    response => {        
        if (response.status === 200) {            
            return Promise.resolve(response);        
        } else {            
            return Promise.reject(response);        
        }    
    },
    // 服務(wù)器狀態(tài)碼不是200的情況    
    error => {        
        if (error.response.status) {            
            switch (error.response.status) {                
                // 401: 未登錄                
                // 未登錄則跳轉(zhuǎn)登錄頁面烹植,并攜帶當(dāng)前頁面的路徑                
                // 在登錄成功后返回當(dāng)前頁面,這一步需要在登錄頁操作愕贡。                
                case 401:                    
                    router.replace({                        
                        path: '/login',                        
                        query: { redirect: router.currentRoute.fullPath } 
                    });
                    break;
                // 403 token過期                
                // 登錄過期對用戶進(jìn)行提示                
                // 清除本地token和清空vuex中token對象                
                // 跳轉(zhuǎn)登錄頁面                
                case 403:                     
                    Toast({                        
                        message: '登錄過期草雕,請重新登錄',                        
                        duration: 1000,                        
                        forbidClick: true                    
                    });                    
                    // 清除token                    
                    localStorage.removeItem('token');                    
                    store.commit('loginSuccess', null);                    
                    // 跳轉(zhuǎn)登錄頁面,并將要瀏覽的頁面fullPath傳過去固以,登錄成功后跳轉(zhuǎn)需要訪問的頁面
                    setTimeout(() => {                        
                        router.replace({                            
                            path: '/login',                            
                            query: { 
                                redirect: router.currentRoute.fullPath 
                            }                        
                        });                    
                    }, 1000);                    
                    break; 
                // 404請求不存在                
                case 404:                    
                    Toast({                        
                        message: '網(wǎng)絡(luò)請求不存在',                        
                        duration: 1500,                        
                        forbidClick: true                    
                    });                    
                break;                
                // 其他錯(cuò)誤墩虹,直接拋出錯(cuò)誤提示                
                default:                    
                    Toast({                        
                        message: error.response.data.message,                        
                        duration: 1500,                        
                        forbidClick: true                    
                    });            
            }            
            return Promise.reject(error.response);        
        }       
    }
);
/** 
 * get方法,對應(yīng)get請求 
 * @param {String} url [請求的url地址] 
 * @param {Object} params [請求時(shí)攜帶的參數(shù)] 
 */
export function get(url, params){    
    return new Promise((resolve, reject) =>{        
        axios.get(url, {            
            params: params        
        })        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}
/** 
 * post方法憨琳,對應(yīng)post請求 
 * @param {String} url [請求的url地址] 
 * @param {Object} params [請求時(shí)攜帶的參數(shù)] 
 */
export function post(url, params) {    
    return new Promise((resolve, reject) => {         
        axios.post(url, QS.stringify(params))        
        .then(res => {            
            resolve(res.data);        
        })        
        .catch(err => {            
            reject(err.data)        
        })    
    });
}

三. http.js和 api.js

http.js是封裝好的axios, api.js 是把業(yè)務(wù)中接口 統(tǒng)一放在這個(gè)文件里,
具體根據(jù)項(xiàng)目進(jìn)行定制化的封裝可以參考axios封裝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末诫钓,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子栽渴,更是在濱河造成了極大的恐慌尖坤,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件闲擦,死亡現(xiàn)場離奇詭異慢味,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)墅冷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門纯路,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寞忿,你說我怎么就攤上這事驰唬。” “怎么了腔彰?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵叫编,是天一觀的道長。 經(jīng)常有香客問我霹抛,道長搓逾,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任杯拐,我火速辦了婚禮霞篡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘端逼。我一直安慰自己朗兵,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布顶滩。 她就那樣靜靜地躺著余掖,像睡著了一般。 火紅的嫁衣襯著肌膚如雪礁鲁。 梳的紋絲不亂的頭發(fā)上浊吏,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機(jī)與錄音救氯,去河邊找鬼找田。 笑死,一個(gè)胖子當(dāng)著我的面吹牛着憨,可吹牛的內(nèi)容都是我干的墩衙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼甲抖,長吁一口氣:“原來是場噩夢啊……” “哼漆改!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起准谚,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤挫剑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后柱衔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體樊破,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愉棱,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了哲戚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奔滑。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖顺少,靈堂內(nèi)的尸體忽然破棺而出朋其,到底是詐尸還是另有隱情,我是刑警寧澤脆炎,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布梅猿,位于F島的核電站,受9級特大地震影響秒裕,放射性物質(zhì)發(fā)生泄漏袱蚓。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一簇爆、第九天 我趴在偏房一處隱蔽的房頂上張望癞松。 院中可真熱鬧,春花似錦入蛆、人聲如沸响蓉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽枫甲。三九已至,卻和暖如春扼褪,著一層夾襖步出監(jiān)牢的瞬間想幻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工话浇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留脏毯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓幔崖,卻偏偏與公主長得像食店,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子赏寇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348