1.寫在前面
最近在學(xué)習Vue2丸相,遇到有些頁面請求數(shù)據(jù)需要用戶登錄權(quán)限搔确、服務(wù)器響應(yīng)不符預(yù)期的問題,但是總不能每個頁面都做單獨處理吧灭忠,于是想到axios提供了攔截器這個好東西膳算,再于是就出現(xiàn)了本文。
2.具體需求
- 用戶鑒權(quán)與重定向:使用Vue提供的路由導(dǎo)航鉤子
- 請求數(shù)據(jù)序列化:使用axios提供的請求攔截器
- 接口報錯信息處理:使用axios提供的響應(yīng)攔截器
3.簡單實現(xiàn)
3.1 路由導(dǎo)航鉤子層面鑒權(quán)與重定向的封裝
路由導(dǎo)航鉤子所有配置均在router/index.js弛作,這里是部分代碼
import Vue from 'vue'
import Router from 'vue-router'
import { getUserData } from '@/script/localUserData'
const MyAddress = r => require.ensure([], () => r(require('@/views/MyAddress/MyAddress')), 'MyAddress')
Vue.use(Router)
const routes = [
{
path: '/profile/address',
name: 'MyAddress',
component: MyAddress,
meta: {
title: '我的地址',
requireAuth: true
}
},
// 更多...
]
const router = new Router({
mode: 'history',
routes
})
我們主要來看下面邏輯處理部分的代碼
let indexScrollTop = 0
router.beforeEach((to, from, next) => {
// 路由進入下一個路由對象前涕蜂,判斷是否需要登陸
// 在路由meta對象中由個requireAuth字段,只要此字段為true缆蝉,必須做鑒權(quán)處理
if (to.matched.some(res => res.meta.requireAuth)) {
// userData為存儲在本地的一些用戶信息
let userData = getUserData()
// 未登錄和已經(jīng)登錄的處理
// getUserData方法處理后如果userData.token沒有值就是undefined宇葱,下面直接判斷
if (userData.token === undefined) {
// 執(zhí)行到此處說明沒有登錄,君可按需處理之后再執(zhí)行如下方法去登錄頁面
// 我這里沒有其他處理刊头,直接去了登錄頁面
next({
path: '/login',
query: {
redirect: to.path
}
})
} else {
// 執(zhí)行到說明本地存儲有用戶信息
// 但是用戶信息是否過期還是需要驗證一下滴
let overdueTime = userData.overdueTime
let nowTime = +new Date
// 登陸過期和未過期
if (nowTime > overdueTime) {
// 登錄過期的處理黍瞧,君可按需處理之后再執(zhí)行如下方法去登錄頁面
// 我這里沒有其他處理,直接去了登錄頁面
next({
path: '/login',
query: {
redirect: to.path
}
})
} else {
next()
}
}
} else {
next()
}
if (to.path !== '/') {
indexScrollTop = document.body.scrollTop
}
document.title = to.meta.title || document.title
})
router.afterEach(route => {
if (route.path !== '/') {
document.body.scrollTop = 0
} else {
Vue.nextTick(() => {
document.body.scrollTop = indexScrollTop
})
}
})
export default router
至此原杂,路由鉤子層面的鑒權(quán)處理完畢印颤,不過細心的你可能注意到:導(dǎo)航去登錄頁面調(diào)用的next方法里面有個query對象,攜帶了目標路由的地址穿肄,這是因為在登錄成功后我們需要重定向到目標頁面年局。
3.2 對axios攔截器封裝
axios所有配置均在件script/getData.js文件际看,這里是本文件公共代碼部分
import qs from 'qs'
import { getUserData } from '@/script/localUserData'
import router from '@/router'
import axios from 'axios'
import { AJAX_URL } from '@/config/index'
axios.defaults.baseURL = AJAX_URL
axios請求攔截器代碼
/**
* 請求攔截器,請求發(fā)送之前做些事情
*/
axios.interceptors.request.use(
config => {
// POST || PUT || DELETE請求時先格式化data數(shù)據(jù)
// 這里需要引入第三方模塊qs
if (
config.method.toLocaleUpperCase() === 'POST' ||
config.method.toLocaleUpperCase() === 'PUT' ||
config.method.toLocaleUpperCase() === 'DELETE'
) {
config.data = qs.stringify(config.data)
}
// 配置Authorization參數(shù)攜帶用戶token
let userData = getUserData()
if (userData.token) {
config.headers.Authorization = userData.token
}
return config
},
error => {
// 此處應(yīng)為彈窗顯示具體錯誤信息矢否,因為是練手項目仲闽,劣者省略此處
// 君可自行寫 || 引入第三方UI框架
console.error(error)
return Promise.reject(error)
}
)
axios響應(yīng)攔截器代碼
/**
* 響應(yīng)攔截器,請求返回異常統(tǒng)一處理
*/
axios.interceptors.response.use(
response => {
// 這段代碼很多場景下沒用
if (response.data && response.data.success === false) {
// 根據(jù)實際情況的一些處理邏輯...
return Promise.reject(response)
}
return response
},
error => {
// 此處報錯可能因素比較多
// 1.需要授權(quán)處用戶還未登錄僵朗,因為路由段有驗證是否登陸赖欣,此處理論上不會出現(xiàn)
// 2.需要授權(quán)處用戶登登錄過期
// 3.請求錯誤 4xx
// 5.服務(wù)器錯誤 5xx
// 關(guān)于鑒權(quán)失敗,與后端約定狀態(tài)碼為500
switch (error.response.status) {
case 403:
// 一些處理...
break
case 404:
// 一些處理...
break
case 500:
let userData = getUserData()
if (userData.token === undefined) {
// 此處為未登錄處理
// 一些處理之后...再去登錄頁面...
// router.push({
// path: '/login'
// })
} else {
let overdueTime = userData.overdueTime
let nowTime = +new Date
if (overdueTime && nowTime > overdueTime) {
// 此處登錄過期的處理
// 一些處理之后...再去登錄頁面...
// router.push({
// path: '/login'
// })
} else {
// 極端情況验庙,登錄未過期顶吮,但是不知道哪兒錯了
// 按需處理吧...我暴力回到了首頁
router.push({
path: '/'
})
}
}
break
case 501:
// 一些處理...
break
default:
// 狀態(tài)碼辣么多,按需配置...
break
}
return Promise.reject(error)
}
)
想了解更多關(guān)于axios的信息粪薛?請移步這里悴了。
這個封裝很簡單,面對復(fù)雜的業(yè)務(wù)肯定還需要更多的考量违寿,但是對于一般的小項目或邊緣業(yè)務(wù)也差不多夠用了湃交。最后希望這篇文章能對有需要的同學(xué)提供一些幫助。