css
應用場景,項目中涉及100個AJAX
請求,其中:vue
1.其中60個須要在請求頭header設置token headers: {token: token}
用於權限校驗;ios
2.其中20個爲上傳EXCEL文件須要在請求頭中設置Content-Type;vuex
headers: {
'Content-Type': `multipart/form-data; boundary=${data._boundary}`
}
上面說的 一、二、3能夠在全局request
攔截中進行處理,可是代價極大,須要爲這100個接口都作判斷再作相應處理... ;固然也能夠不用全局攔截,爲每一個接口都單獨定義,我相信有很多同窗還是這樣處理的,可是只要有改動,例如如今我要求全部的請求頭都新增一個參數,那就只能一個一個接口的改.....這不是咱們想要的結果,因此 咱們須要對AJAX再封裝!AJAX再封裝!AJAX再封裝!,由於至關重要,因此要多說幾遍....element-ui
③最後20個請求用來獲取文件流
,須要指定接受類型responseType: 'blob'
json
須要對全局發起request進行攔截並作異步處理(強調:是異步處理);axios
若是你的項目已經作到一半,如今後端要加上token權限作認證;後端
封裝其實很簡單,就是對原來真正的AJAX套一個殼,這個殼就是一個函數! 在這個函數裏都幹了些什麼見不得人事呢?幹什麼均可以,上面說的一、 二、 三、 四、 5均可以在這裏悄悄的進行,那對原來的AJAX鏈式調用有影響嗎?答案是確定的:沒有影響。 先來看看我在代碼裏調用的AJAX:api
_initEditParams () {
this.$axios('Common/Permission/Get', {Id}).then(res => {
....
....
})
},
this.$axios能夠直接調用是由於這裏把請求方法之類的配置項全放在封裝裏面進行了。服務器
這裏也是經過Vue.prototype.$axios = axios
添加到vue全局實例的,但這裏添加的axios
不是直接引入的axios插件,而是一個方法
import {axios} from './utils/common'
Vue.prototype.$axios = axios
固然。也能夠不用添加到全局實例裏面,能夠在組件中經過import
語法引入使用。固然是項目裏大量使用的封裝方法直接使用Vue.prototype
添加到vue
實例。接下來咱們看看axios方法都作了些啥:
import Axios from 'axios'
import Store from '../vuex'
/*********************************
** Fn: axios
** Intro: 公用封裝的axios 已在main.js中進行 $axios代理
** Intro: Store.state.permission.constUrl 爲公用的接口前綴地址
** Intro: url 方法接受參數 爲定義的 接口地址後綴
** Intro: data 方法接受參數 爲定義的參數
** Author: zyx
*********************************/
export function axios (url, data) {
return new Promise((resolve, reject) => {
Axios({
url: `${Store.state.permission.constUrl}${url}`,
method: 'post',
data: data,
headers: {
token: Store.state.permission.token
}
}).then(res => {
resolve(res)
}).catch(err => {
reject(err)
})
})
}
Axios的封裝
在目錄下新建一個Axios文件夾,在文件夾下新建文件axios.js,文件內容:
import Axios from "axios";
import qs from "qs";
import router from "@/router/router.js";
// import { Message } from "element-ui";
/****** 建立axios實例 ******/
const Service = Axios.create({
baseURL: process.env.BASE_URL, // api的base_url
timeout: 10000, // 請求超時時間
responseType: "json",
withCredentials: true, // 是否容許帶cookie這些
headers: {
// "Content-Type": "application/x-www-form-urlencoded;charset=utf-8"
"Content-Type": "application/json;charset=utf-8"
}
});
// 設置請求攔截器
Service.interceptors.request.use(config => {
// 在發送請求以前作某件事
if (config.method === "post") {
// 序列化
// config.data = qs.stringify(config.data);
// config.data = JSON.stringify(config.data);
// 舒適提示,如果公司的提交能直接接受json 格式,能夠不用 qs 來序列化的
}
// 如果有作鑑權token , 就給頭部帶上token
// 如果須要跨站點,存放到 cookie 會好一點,限制也沒那麼多,有些瀏覽環境限制了 localstorage 的使用
// if (localStorage.token) {
// config.headers.Authorization = localStorage.token;
// }
return config;
},
error => {
// error 的回調信息,看公司的定義
Message({
showClose: true,
message: error,
type: "warning"
});
return Promise.reject(error);
})
// 響應攔截 http 請求回來的一些狀態碼,包括咱們本身的服務器返回的錯誤碼進行一個邏輯處理。
Service.interceptors.response.use(res => {
//對響應數據作些事
// 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) => {
// 錯誤處理方式1:
// if (error.data) {
// switch (error.data.code) {
// case 401:
// // 返回 401 清除token信息並跳轉到登陸頁面
// // store.commit("del_token");
// router.push({
// path: "/login",
// // 記錄原來的頁面路徑用於登陸後調回原頁面
// query: {
// redirect: router.currentRoute.fullPath
// }
// });
// break;
// }
// }
// 錯誤處理方式2:
// 用戶登陸的時候會拿到一個基礎信息,好比用戶名,token,過時時間戳
// 直接丟localStorage或者sessionStorage
if (!window.localStorage.getItem("username")) {
// 如果接口訪問的時候沒有發現有鑑權的基礎信息,直接返回登陸頁
router.push({
path: "/login"
});
} else {
// 下面是接口回調的satus ,由於我作了一些錯誤頁面,因此都會指向對應的報錯頁面
if (error.response.status === 403) {
router.push({
path: "/error/403"
});
}
if (error.response.status === 500) {
router.push({