Vue之Axios攔截器使用及說明
在實(shí)際開發(fā)中有時(shí)需要統(tǒng)一處理HTTP的請(qǐng)求和響應(yīng),會(huì)在請(qǐng)求或響應(yīng)被 then 或 catch 處理前攔截它們。
比如會(huì)員登錄安全驗(yàn)證,這時(shí)使用攔截器可以很輕松的實(shí)現(xiàn),先看一下攔截器的語法形式代碼如下:
// 添加請(qǐng)求攔截器
axios.interceptors.request.use(function (config) {
// 在發(fā)送請(qǐng)求之前做些什么
return config;
}, function (error) {
// 對(duì)請(qǐng)求錯(cuò)誤做些什么
return Promise.reject(error);
});
// 添加響應(yīng)攔截器
axios.interceptors.response.use(function (response) {
// 對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么
return response;
}, function (error) {
// 對(duì)響應(yīng)錯(cuò)誤做點(diǎn)什么
return Promise.reject(error);
});
HTTP請(qǐng)求和響應(yīng)攔截器是一種在HTTP請(qǐng)求發(fā)送之前和響應(yīng)接收之后,對(duì)請(qǐng)求和響應(yīng)進(jìn)行統(tǒng)一處理的方式。
通過攔截器,可以在不修改每個(gè)請(qǐng)求處理邏輯的情況下,對(duì)所有HTTP請(qǐng)求和響應(yīng)進(jìn)行統(tǒng)一的處理。
在Axios中,可以通過axios.interceptors.request和axios.interceptors.response來添加請(qǐng)求和響應(yīng)攔截器。
攔截器允許我們?cè)谡?qǐng)求發(fā)送前修改請(qǐng)求配置,或者在響應(yīng)接收后修改響應(yīng)數(shù)據(jù),也可以在請(qǐng)求或響應(yīng)出錯(cuò)時(shí)進(jìn)行處理。
1.請(qǐng)求攔截器
axios.interceptors.request.use(function (config) {
// 在發(fā)送請(qǐng)求之前做些什么
return config;
}, function (error) {
// 對(duì)請(qǐng)求錯(cuò)誤做些什么
return Promise.reject(error);
});
這個(gè)攔截器會(huì)在每次HTTP請(qǐng)求發(fā)送之前被調(diào)用,可以修改請(qǐng)求的配置(如添加請(qǐng)求頭、修改請(qǐng)求參數(shù)等)。
如果發(fā)生錯(cuò)誤,可以在這里進(jìn)行處理,并返回一個(gè)被拒絕的Promise。
2.響應(yīng)攔截器
axios.interceptors.response.use(function (response) {
// 對(duì)響應(yīng)數(shù)據(jù)做點(diǎn)什么
return response;
}, function (error) {
// 對(duì)響應(yīng)錯(cuò)誤做點(diǎn)什么
return Promise.reject(error);
});
這個(gè)攔截器會(huì)在每次HTTP響應(yīng)接收后被調(diào)用,可以修改響應(yīng)數(shù)據(jù),或者在響應(yīng)出錯(cuò)時(shí)進(jìn)行處理。
例如,可以統(tǒng)一處理401未認(rèn)證錯(cuò)誤,跳轉(zhuǎn)到登錄頁面。
3.在實(shí)際開發(fā)中有時(shí)需要統(tǒng)一處理HTTP的請(qǐng)求和響應(yīng),這句該如何理解?
我的理解是,統(tǒng)一處理HTTP請(qǐng)求和響應(yīng)意味著在整個(gè)應(yīng)用中,對(duì)所有的HTTP請(qǐng)求和響應(yīng)進(jìn)行一致的處理,而不需要在每個(gè)請(qǐng)求的地方重復(fù)相同的邏輯。
例如,可以在請(qǐng)求攔截器中添加統(tǒng)一的認(rèn)證頭,或者在響應(yīng)攔截器中統(tǒng)一處理錯(cuò)誤狀態(tài)碼。
攔截器一定要封裝我在utils文件下建立一個(gè)http.js文件
http.js文件
import Axios from "axios";
import _config from "../conf/confg"; //引入baseAPI
import qs from "qs";
//導(dǎo)出名叫request_name的一個(gè)方法
export function request_name(config1 = {})
{//創(chuàng)建實(shí)例
let service = Axios.create({ baseURL: _config.baseApi });
return service.request(config1);
}
main.js文件
import Vue from "vue";
//將request_name方法掛載到全局上
import { request_name } from "./assets/js/utils/http";
Vue.prototype.$requestname = request_name;
new Vue({
router,
store, //注冊(cè)store
render: (h) => h(App),
}).$mount("#app");
做登錄驗(yàn)證
login.vue
<template>
<div>
用戶名:<input type="text" v-model="uname" /> <br />
密碼:<input type="password" v-model="upassword" />
<button type="button" @click="submit()">提交</button>
</div>
</template>
<script>
export default{
name :"user-name",
data(){
return{
uname:"",
upassword:""
}
},
methods:{
submit(){
if(this.uname==""){alert("請(qǐng)輸入姓名"); return;}
if(this.upassword==""){ alert("請(qǐng)輸入密碼"); return;}
this.$requestname({
url:"/home/user/pwdlogin?token="+this.$config.token,
method:"post",
data:{cellphone:this.uname,password:this.upassword}
//使用request_name函數(shù)返回的結(jié)果
}).then( res=>{console.log(res),
localStorage['uname']=res.data.nickname;
localStorage['uid']=res.data.uid;
localStorage['authToken']=res.data.auth_token;
localStorage['isLogin']=true;
this.$router.replace("/")
} )
}
}
}
</script>
由于這里的post數(shù)據(jù)要類型轉(zhuǎn)換,所以我們可以在請(qǐng)求攔截器中,完成數(shù)據(jù)類型轉(zhuǎn)換
data:{cellphone:this.uname,password:this.upassword}
http.js文件
import Axios from "axios";
import _config from "../conf/confg";
import qs from "qs"; //這里的post數(shù)據(jù)類型轉(zhuǎn)換我們用攔截器來做
//導(dǎo)出名叫request_name的一個(gè)方法
export function request_name(config1 = {} ) {
//創(chuàng)建實(shí)例
let service = Axios.create({ baseURL: _config.baseApi });
//請(qǐng)求攔截器來做post數(shù)據(jù)轉(zhuǎn)換
service.interceptors.request.use( (config) => {
console.log(config);// 攔截器修改邏輯“這里是打印”
return config;//將修改后的配置項(xiàng)返回
}, (error) => {
return Promise.reject(error);
})
return service.request(config1)
}
問題1:請(qǐng)求攔截器是如何被調(diào)用的
- 1.創(chuàng)建了一個(gè)獨(dú)立的 Axios 實(shí)例 service,并配置了 baseURL
- 2. 注冊(cè)動(dòng)作:通過 interceptors.request.use 將攔截器函數(shù)掛載到 Axios 實(shí)例上。
- 3. 此時(shí)攔截器并未執(zhí)行,只是完成注冊(cè)。
- 4. 當(dāng)調(diào)用 request_name 方法時(shí),實(shí)際執(zhí)行的是 service.request(config1)。
- 5. 此時(shí) Axios 內(nèi)部會(huì)自動(dòng)觸發(fā)已注冊(cè)的攔截器。
- 6. 這里的攔截器中的動(dòng)作是打印 config對(duì)象console.log(config)
- 7. 攔截器是自動(dòng)觸發(fā)的,只要通過 service.request() 或快捷方法
(如 service.get()、service.post())發(fā)起請(qǐng)求,所有注冊(cè)的攔截器會(huì)自動(dòng)執(zhí)行。
?只要通過 service.request() 或快捷方法(如 service.get()、service.post())發(fā)起請(qǐng)求,所有注冊(cè)的攔截器會(huì)自動(dòng)執(zhí)行。
問題2: service.interceptors.request.use( (config) => { }中的config完全來自service.request(config1)中的config1嗎?
攔截器中的 config 參數(shù)本質(zhì)來源于你調(diào)用 service.request(config1) 時(shí)傳入的 config1 ,但并非直接等同于 config1。Axios 在內(nèi)部對(duì)配置進(jìn)行了 多層合并處理,最終傳遞給攔截器的 config 是合并后的完整配置對(duì)象。
以下是詳細(xì)流程分析:
一、config 的生成過程
當(dāng)調(diào)用 service.request(config1) 時(shí),Axios 會(huì)通過以下步驟生成最終的 config 對(duì)象:
三層配置
- 1.Axios 全局默認(rèn)配置:包括 headers 的默認(rèn)值(如 Accept 和 Content-Type)。
- 2.實(shí)例級(jí)默認(rèn)配置:通過 Axios.create({ baseURL: ... }) 設(shè)置的配置(如 baseURL)。
- 3. 請(qǐng)求級(jí)配置:調(diào)用 service.request(config1) 時(shí)傳入的 config1。
Axios 會(huì)將這三層配置合并,形成最終的 config 對(duì)象,傳遞給攔截器。config對(duì)象包含完整的請(qǐng)求信息:如 url、method、data、headers、timeout 等。

import Axios from "axios";
import _config from "../conf/confg";
import qs from "qs"; //這里的post數(shù)據(jù)類型轉(zhuǎn)換我們用攔截器來做
//導(dǎo)出名叫request_name的一個(gè)方法
export function request_name(config1 = {} ) {
//創(chuàng)建實(shí)例
let service = Axios.create({ baseURL: _config.baseApi });
//請(qǐng)求攔截器來做post數(shù)據(jù)轉(zhuǎn)換
service.interceptors.request.use( (config) => {
console.log(config);// 攔截器修改邏輯“這里是打印”
if (config.method.toLocaleLowerCase() === "post")
{ config.data = qs.stringify(config.data);}
return config;//將修改后的配置項(xiàng)返回
}, (error) => { return Promise.reject(error); })
return service.request(config1).then((res) => res.data);
}
return service.request(config1).then((res) => res.data);請(qǐng)求成功后,把響應(yīng)結(jié)果,由res接收,提取響應(yīng)數(shù)據(jù) res.data 并返回。
寫這一步的目的then((res) => res.data)是為了簡(jiǎn)化調(diào)用數(shù)據(jù)的步驟



localStorage存儲(chǔ)用戶信息。這可能是因?yàn)樾枰诙鄠€(gè)頁面或?yàn)g覽器會(huì)話中保持用戶登錄狀態(tài),而localStorage提供了持久化存儲(chǔ)的能力。存儲(chǔ)的信息包括昵稱、用戶ID、認(rèn)證令牌和登錄狀態(tài),這些都是維持用戶會(huì)話的關(guān)鍵數(shù)據(jù)。
會(huì)員登錄認(rèn)證的核心就是:驗(yàn)證我們localStorage本地緩存的token,跟我服務(wù)器上的token值是否一致,如果一致則算你登錄成功,如果不一致則登錄失敗,要跳到登錄頁面去
<template>
<div>
歡迎{{name1}}回來<br />{{message}}<br />
<button type="button" @click="outLogin()">安全返回</button>
</div>
</template>
<script>
export default{
name:"person-name",
data(){
return{name1: localStorage['uname'],
message:""
}
},
---------------------------------------------
安全認(rèn)證就用它
created(){
this.$requestname({
url:"/home/user/safe?token="+this.$config.token,
method:'post', //將本地?cái)?shù)據(jù)uid和token拿到服務(wù)器做對(duì)比
data:{uid:localStorage['uid'],auth_token:localStorage['authToken']}
},this.$riuter).then(res=>{console.log(res)})
},
--------------------------------------------------
methods:{
outLogin(){
//安全退出
this.$requestname({
url:"/home/user/safeout?token="+this.$config.token,
method:"post",
data:{uid:localStorage["uid"]}
}).then( res=>{console.log(res)
if(res.code==200){
localStorage.removeItem("unname") ;
localStorage.removeItem("isLogin") ;
localStorage.clear();//清除所有本地緩存
this.$router.replace("/login");
}
} )
}
},
}
</script>

有權(quán)限訪問說明:將本地?cái)?shù)據(jù)uid和token跟服務(wù)器接口的數(shù)據(jù)一致,也同時(shí)說明,登錄成功

安全退出:清除本地緩存

import Axios from "axios";
import _config from "../conf/confg";
import qs from "qs"; //這里的post數(shù)據(jù)類型轉(zhuǎn)換我們用攔截器來做
//導(dǎo)出名叫request_name的一個(gè)方法
export function request_name(config1 = {}, router) {
//創(chuàng)建實(shí)例
let service = Axios.create({ baseURL: _config.baseApi });
//-------------------------------------------------------------------------------
//請(qǐng)求攔截器來做post數(shù)據(jù)轉(zhuǎn)換
service.interceptors.request.use(
(config) => {
console.log(config);
if (config.method.toLocaleLowerCase() === "post") {
config.data = qs.stringify(config.data);
} else if (config.method.toLocaleLowerCase() === "file") {
config.method = "post";
let formData = new FormData();
if (config.data instanceof Object) {
for (let key in config) {
formData.append(key, config.data[key]);
}
config.data = formData;
}
// config.method = "post";
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
//--------------------------------------------------------------
//響應(yīng)攔截器
service.interceptors.response.use(
(response) => {
console.log(response); //判斷是否調(diào)用了會(huì)員安全認(rèn)證接口了
if (response.config.url == "/home/user/safe?token=1ec949a15fb709370f") {
if (response.data.code != 200) {
//沒有調(diào)用了會(huì)員安全認(rèn)證接口,即登錄驗(yàn)證失敗
localStorage.clear();//清除緩存
router.replace("/login");
//跳到登錄頁面(這里的路由是從request_name中傳進(jìn)來的)
}
}
return response;
},
(error) => {
return Promise.reject(error);
}
);
//------------------------------------------------------------------------------
return service.request(config1).then((res) => res.data);
}
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Vue.js實(shí)現(xiàn)的計(jì)算器功能完整示例
這篇文章主要介紹了Vue.js實(shí)現(xiàn)的計(jì)算器功能,結(jié)合完整實(shí)例形式分析了vue.js響應(yīng)鼠標(biāo)事件實(shí)現(xiàn)基本的數(shù)值運(yùn)算相關(guān)操作技巧,可實(shí)現(xiàn)四則運(yùn)算及乘方、開方等功能,需要的朋友可以參考下2018-07-07
vue3循環(huán)展示圖片實(shí)現(xiàn)過程
這篇文章主要介紹了vue3循環(huán)展示圖片實(shí)現(xiàn)過程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
Vue+element使用row-class-name修改el-table某一行解決背景色無效的方法
本文主要介紹了Vue+element使用row-class-name修改el-table某一行解決背景色無效的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01
Vue3實(shí)現(xiàn)自定義Input組件的示例詳解
這篇文章主要為大家詳細(xì)介紹了如何使用Vue3自定義實(shí)現(xiàn)一個(gè)類似el-input的組件,可以v-model雙向綁定,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-03-03
vue 做移動(dòng)端微信公眾號(hào)采坑經(jīng)驗(yàn)記錄
這篇文章主要介紹了vue 做移動(dòng)端微信公眾號(hào)采坑經(jīng)驗(yàn)記錄,文中是小編記錄的三個(gè)坑及解決方案,需要的朋友可以參考下2018-04-04
vue 中的動(dòng)態(tài)傳參和query傳參操作
這篇文章主要介紹了vue 中的動(dòng)態(tài)傳參和query傳參操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-11-11
vue使用高德地圖根據(jù)坐標(biāo)定位點(diǎn)的實(shí)現(xiàn)代碼
這篇文章主要介紹了vue使用高德地圖根據(jù)坐標(biāo)定位點(diǎn)的實(shí)現(xiàn)代碼,代碼簡(jiǎn)單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08

