Vue中axios的封裝(報(bào)錯(cuò)、鑒權(quán)、跳轉(zhuǎn)、攔截、提示)
- 統(tǒng)一捕獲接口報(bào)錯(cuò)
- 彈窗提示
- 報(bào)錯(cuò)重定向
- 基礎(chǔ)鑒權(quán)
- 表單序列化
實(shí)現(xiàn)的功能
- 統(tǒng)一捕獲接口報(bào)錯(cuò) : 用的axios內(nèi)置的攔截器
- 彈窗提示: 引入 Element UI 的 Message 組件
- 報(bào)錯(cuò)重定向: 路由鉤子
- 基礎(chǔ)鑒權(quán): 服務(wù)端過期時(shí)間戳和token,還有借助路由的鉤子
- 表單序列化: 我這邊直接用 qs (npm模塊),你有時(shí)間也可以自己寫
用法及封裝
用法
// 服務(wù)層 , import默認(rèn)會(huì)找該目錄下index.js的文件,這個(gè)可能有小伙伴不知道
// 可以去了解npm的引入和es6引入的理論概念
import axiosPlugin from "./server";
Vue.use(axiosPlugin);
對(duì)axios的封裝(AXIOS: index.js )
import axios from "axios";
import qs from "qs";
import { Message } from "element-ui";
import router from "../router";
const Axios = axios.create({
baseURL: "/", // 因?yàn)槲冶镜刈隽朔聪虼?
timeout: 10000,
responseType: "json",
withCredentials: true, // 是否允許帶cookie這些
headers: {
"Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
}
});
//POST傳參序列化(添加請(qǐng)求攔截器)
Axios.interceptors.request.use(
config => {
// 在發(fā)送請(qǐng)求之前做某件事
if (
config.method === "post"
) {
// 序列化
config.data = qs.stringify(config.data);
// 溫馨提示,若是貴公司的提交能直接接受json 格式,可以不用 qs 來(lái)序列化的
}
// 若是有做鑒權(quán)token , 就給頭部帶上token
// 若是需要跨站點(diǎn),存放到 cookie 會(huì)好一點(diǎn),限制也沒那么多,有些瀏覽環(huán)境限制了 localstorage 的使用
// 這里localStorage一般是請(qǐng)求成功后我們自行寫入到本地的,因?yàn)槟惴旁趘uex刷新就沒了
// 一些必要的數(shù)據(jù)寫入本地,優(yōu)先從本地讀取
if (localStorage.token) {
config.headers.Authorization = localStorage.token;
}
return config;
},
error => {
// error 的回調(diào)信息,看貴公司的定義
Message({
// 餓了么的消息彈窗組件,類似toast
showClose: true,
message: error && error.data.error.message,
type: 'error'
});
return Promise.reject(error.data.error.message);
}
);
//返回狀態(tài)判斷(添加響應(yīng)攔截器)
Axios.interceptors.response.use(
res => {
//對(duì)響應(yīng)數(shù)據(jù)做些事
if (res.data && !res.data.success) {
Message({
// 餓了么的消息彈窗組件,類似toast
showClose: true,
message: res.data.error.message.message
? res.data.error.message.message
: res.data.error.message,
type: "error"
});
return Promise.reject(res.data.error.message);
}
return res;
},
error => {
// 用戶登錄的時(shí)候會(huì)拿到一個(gè)基礎(chǔ)信息,比如用戶名,token,過期時(shí)間戳
// 直接丟localStorage或者sessionStorage
if (!window.localStorage.getItem("loginUserBaseInfo")) {
// 若是接口訪問的時(shí)候沒有發(fā)現(xiàn)有鑒權(quán)的基礎(chǔ)信息,直接返回登錄頁(yè)
router.push({
path: "/login"
});
} else {
// 若是有基礎(chǔ)信息的情況下,判斷時(shí)間戳和當(dāng)前的時(shí)間,若是當(dāng)前的時(shí)間大于服務(wù)器過期的時(shí)間
// 乖乖的返回去登錄頁(yè)重新登錄
let lifeTime =
JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime *
1000;
let nowTime = new Date().getTime(); // 當(dāng)前時(shí)間的時(shí)間戳
console.log(nowTime, lifeTime);
console.log(nowTime > lifeTime);
if (nowTime > lifeTime) {
Message({
showClose: true,
message: "登錄狀態(tài)信息過期,請(qǐng)重新登錄",
type: "error"
});
router.push({
path: "/login"
});
} else {
// 下面是接口回調(diào)的satus ,因?yàn)槲易隽艘恍╁e(cuò)誤頁(yè)面,所以都會(huì)指向?qū)?yīng)的報(bào)錯(cuò)頁(yè)面
if (error.response.status === 403) {
router.push({
path: "/error/403"
});
}
if (error.response.status === 500) {
router.push({
path: "/error/500"
});
}
if (error.response.status === 502) {
router.push({
path: "/error/502"
});
}
if (error.response.status === 404) {
router.push({
path: "/error/404"
});
}
}
}
// 返回 response 里的錯(cuò)誤信息
let errorInfo = error.data.error ? error.data.error.message : error.data;
return Promise.reject(errorInfo);
}
);
// 對(duì)axios的實(shí)例重新封裝成一個(gè)plugin ,方便 Vue.use(xxxx)
export default {
install: function(Vue, Option) {
Object.defineProperty(Vue.prototype, "$http", { value: Axios });
}
};
路由鉤子的調(diào)整(Router: index.js )
import Vue from "vue";
import Router from "vue-router";
import layout from "@/components/layout/layout";
// 版塊有點(diǎn)多,版塊獨(dú)立路由管理,里面都是懶加載引入
import customerManage from "./customerManage"; // 客戶管理
import account from "./account"; //登錄
import adManage from "./adManage"; // 廣告管理
import dataStat from "./dataStat"; // 數(shù)據(jù)統(tǒng)計(jì)
import logger from "./logger"; // 日志
import manager from "./manager"; // 管理者
import putonManage from "./putonManage"; // 投放管理
import error from "./error"; // 服務(wù)端錯(cuò)誤
import { Message } from "element-ui";
Vue.use(Router);
// 請(qǐng)?zhí)^這一段,看下面的
const router = new Router({
hashbang: false,
mode: "history",
routes: [
{
path: "/",
redirect: "/adver",
component: layout,
children: [
...customerManage,
...adManage,
...dataStat,
...putonManage,
...manager,
...logger
]
},
...account,
...error
]
});
// 路由攔截
// 差點(diǎn)忘了說明,不是所有版塊都需要鑒權(quán)的
// 所以需要鑒權(quán),我都會(huì)在路由meta添加添加一個(gè)字段requireLogin,設(shè)置為true的時(shí)候
// 這貨就必須走鑒權(quán),像登錄頁(yè)這些不要,是可以直接訪問的!!!
router.beforeEach((to, from, next) => {
if (to.matched.some(res => res.meta.requireLogin)) {
// 判斷是否需要登錄權(quán)限
if (window.localStorage.getItem("loginUserBaseInfo")) {
// 判斷是否登錄
let lifeTime =
JSON.parse(window.localStorage.getItem("loginUserBaseInfo")).lifeTime *
1000;
let nowTime = (new Date()).getTime(); // 當(dāng)前時(shí)間的時(shí)間戳
if (nowTime < lifeTime) {
next();
} else {
Message({
showClose: true,
message: "登錄狀態(tài)信息過期,請(qǐng)重新登錄",
type: "error"
});
next({
path: "/login"
});
}
} else {
// 沒登錄則跳轉(zhuǎn)到登錄界面
next({
path: "/login"
});
}
} else {
next();
}
});
export default router;
axios可配置的一些選項(xiàng),其他的具體看官網(wǎng)說明哈
export default {
// 請(qǐng)求地址
url: "/user",
// 請(qǐng)求類型
method: "get",
// 請(qǐng)根路徑
baseURL: "http://www.mt.com/api",
// 請(qǐng)求前的數(shù)據(jù)處理
transformRequest: [function(data) {}],
// 請(qǐng)求后的數(shù)據(jù)處理
transformResponse: [function(data) {}],
// 自定義的請(qǐng)求頭
headers: { "x-Requested-With": "XMLHttpRequest" },
// URL查詢對(duì)象
params: { id: 12 },
// 查詢對(duì)象序列化函數(shù)
paramsSerializer: function(params) {},
// request body
data: { key: "aa" },
// 超時(shí)設(shè)置s
timeout: 1000,
// 跨域是否帶Token
withCredentials: false,
// 自定義請(qǐng)求處理
adapter: function(resolve, reject, config) {},
// 身份驗(yàn)證信息
auth: { uname: "", pwd: "12" },
// 響應(yīng)的數(shù)據(jù)格式 json / blob /document /arraybuffer / text / stream
responseType: "json",
// xsrf 設(shè)置
xsrfCookieName: "XSRF-TOKEN",
xsrfHeaderName: "X-XSRF-TOKEN",
// 下傳和下載進(jìn)度回調(diào)
onUploadProgress: function(progressEvent) {
Math.round(progressEvent.loaded * 100 / progressEvent.total);
},
onDownloadProgress: function(progressEvent) {},
// 最多轉(zhuǎn)發(fā)數(shù),用于node.js
maxRedirects: 5,
// 最大響應(yīng)數(shù)據(jù)大小
maxContentLength: 2000,
// 自定義錯(cuò)誤狀態(tài)碼范圍
validateStatus: function(status) {
return status >= 200 && status < 300;
},
// 用于node.js
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// 用于設(shè)置跨域請(qǐng)求代理
proxy: {
host: "127.0.0.1",
port: 8080,
auth: {
username: "aa",
password: "2123"
}
},
// 用于取消請(qǐng)求
cancelToken: new CancelToken(function(cancel) {})
};
總結(jié)
這個(gè)封裝雖說不是萬(wàn)金油版本,但是我感覺大多用axios結(jié)合vue的小伙伴,稍微改改都能直接拿來(lái)用
鑒權(quán)需要再嚴(yán)謹(jǐn)一些,比如token 可以遵循 JWT 的規(guī)格,以及引入中間層nodejs(對(duì)傳輸?shù)淖鰯r截封裝加解密,聚合接口);
以上所述是小編給大家介紹的Vue中axios的封裝(報(bào)錯(cuò)、鑒權(quán)、跳轉(zhuǎn)、攔截、提示),希望對(duì)大家有所幫助,如果大家有任何疑問歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!
相關(guān)文章
vue引入新版 vue-awesome-swiper插件填坑問題
這篇文章主要介紹了vue引入新版 vue-awesome-swiper插件填坑問題,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-01-01
vue自定義組件(通過Vue.use()來(lái)使用)即install的用法說明
這篇文章主要介紹了vue自定義組件(通過Vue.use()來(lái)使用)即install的用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2020-08-08
在Vue3中使用BabylonJs開發(fā)?3D的初體驗(yàn)
這篇文章主要介紹了在?Vue3?中使用?BabylonJs?開發(fā)?3D?是什么體驗(yàn),在本文中,向您展示了如何創(chuàng)建?Vue?組件、Babylon?類、在畫布上渲染場(chǎng)景以及創(chuàng)建?3D?網(wǎng)格,需要的朋友可以參考下2022-07-07
Vue-router的使用和出現(xiàn)空白頁(yè),路由對(duì)象屬性詳解
今天小編就為大家分享一篇Vue-router的使用和出現(xiàn)空白頁(yè),路由對(duì)象屬性詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2018-09-09
Vue中的scoped實(shí)現(xiàn)原理及穿透方法
這篇文章主要介紹了Vue中的scoped實(shí)現(xiàn)原理及穿透方法,本文通過實(shí)例文字相結(jié)合的形式給大家介紹的非常詳細(xì),需要的朋友可以參考下2018-05-05
vue性能優(yōu)化之cdn引入vue-Router的問題
這篇文章主要介紹了vue性能優(yōu)化之cdn引入vue-Router的問題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-08-08

