前端時間項目需要發布一個較大的版本,工作比較忙,加了好多個晚上的班,感覺自己有點缺氧了。最近稍微閑下來了,順便調休了三天,剛剛給家里來了個大掃除,看著這干干凈凈的小家,心里頓時舒服了很多。 
 
下面進入正題(本文以vue項目為例)→
 
 
npm install axios
 
- 然后在 main.js 里引入 axios,然后進行全局掛載在vue原型上
 
import axios from 'axios';
Vue.prototype.$axios = axios;
 
使用方式:
 
 this.$axios.post(api, this.form).then(res => {console.log(111, res)})
 
當然,這里還有另外一種方式讓我們可以在全局直接使用axios
 
 
npm install --save axios vue-axios
 
- 然后在 main.js 里引入 axios,然后使用 vueAxios進行全局掛載
 
import vueAxios from 'vue-axios'
Vue.use(vueAxios, axios);
 
使用方式:
 
Vue.axios.get(api).then((response) => {console.log(response.data)
})this.axios.get(api).then((response) => {console.log(response.data)
})this.$http.get(api).then((response) => {console.log(response.data)
})
 
 
跨域問題:
 在vue或者react項目中,我們大多使用代理的方式來解決跨域問題
 
- 首先,找到 config文件下的 index.js 文件,在proxyTable下加上以下代碼
 
proxyTable: {'/apis': {// 測試環境target: 'http://192.168.0.113',  // 后端接口域名changeOrigin: true,  //是否跨域pathRewrite: {'^/apis': ''   //需要rewrite重寫的,}}},
 
 *tips:因為我們修改了配置文件,所以在這一步之后需要我們重啟項目才可生效
 
接下來就是發送請求,可能我們對于上面剛加的代碼不是很理解,比如說:
 
 這個 '^/apis ’ 是什么意思?
 我們仔細一看,他就像是一個正則表達式:^ 符號代表以什么開頭,這里就是以 /apis 開頭,當我們使用axios發送請求時:
 
 他就會檢測到這里的請求 api 為: ‘/apis/login’ ,是以 /apis 開頭的路徑,那他就會將我們的請求前綴替換成為 ‘http://192.168.0.113’
 
http://localhost:8888/apis/login
等同于:
http://192.168.0.113/login
 
路由攔截
 
我們的項目中很多頁面是需要進行登錄才能瀏覽的,但是如果我們每進入一個頁面都去判斷他是否有登錄(Token),明顯不是一個明智之舉,所以我們需要一個公共的方法去處理這件事情。
 
以 vue-router 為例,我們知道 vue-router 具有兩個全局守衛:
 
全局前置守衛:router.beforeEach((to, from, next) => {// ...
})to: Route: 即將要進入的目標 路由對象
from: Route: 當前導航正要離開的路由
next: Function: 一定要調用該方法來 resolve 這個鉤子。全局后置鉤子:
router.afterEach((to, from) => {// ...
})
 
在這里,我們正是要用到 router.beforeEach 這個鉤子函數
 讓我們來打印康康 to 這個參數有什么東西:
 
 其中里面有一個 mata 的對象,他代表了什么吶?
 
 沒錯,正是它。我們給路徑為 ‘/’ 的這個路由配置一個參數requireAuth
 
// 需要登錄才能進入的頁面可以增加一個meta屬性
meta: { requireAuth: true
},
 
這樣,我們就可以 to 這個參數里找到他了
 
 相信講到這里,你一定有了自己的實現思路了
 
// 判斷是否需要登錄權限 以及是否登錄
router.beforeEach((to, from, next) => {console.log('to', to)const { meta } = to || {}const { requireAuth } = meta || {}// 即將進入的頁面是否需要登錄if(requireAuth) {// 判斷是否有Token(一般用戶登錄之后,后端會返回給我們用戶的Token, 我們將其存放下來,具體存			 到哪里,存儲多長時間,根據你的需要來,這里我是存儲在 localStorage 里)if(localStorage.getItem('NOV_TOKEN')) {// 記住,一定要調用next函數,router才能進行下去next()} else {//  需要登錄卻沒有登錄(無Token),重定向到 登錄頁next({path: '/login',})}} else {// 不需要登錄,直接往下進行next()}})
 
 請求攔截
 
上面,我們對路由進行了攔截,但是有時候雖然我們登錄過,將Token已經存儲在 localStorage 里了,但這也不能完全保證安全,因為 token 一般是具有時效的,登錄(Token)失效后也需要重新登錄。但我們怎么知道Token是否失效了吶?這就需要后端告訴我們了。當我們進入一個需要登錄的頁面,需要發送請求獲取某些數據時,后端會先判斷此人是否有登錄,登錄是否失效,如果失效,后端會返回給我們401登錄失效code碼。當我們接收到 401 code 碼時,就需要重定向到登錄頁,引導用戶進行登錄。
 那這些,就屬于請求攔截的范疇了。
 axios的官方文檔給出了兩個攔截方式:
 
// 添加請求攔截器
axios.interceptors.request.use(function (config) {// 在發送請求之前做些什么return config;}, function (error) {// 對請求錯誤做些什么return Promise.reject(error);});// 添加響應攔截器
axios.interceptors.response.use(function (response) {// 對響應數據做點什么return response;}, function (error) {// 對響應錯誤做點什么return Promise.reject(error);});
 
所以我們就可以在這里進行響應攔截了
 
// 請求響應攔截處理
axios.interceptors.response.use(response => {const { data: { code, message }  } = responseif ( code === '200') {return response;} else if (code === '401') {router.push('/login')} else {ElementUI.Message.error({message: message || '請求失敗',type: 'warning'});}
}, function (error) {return Promise.reject(error)
})
 
 關于這些axios請求,我們都是直接在main.js里進行相關處理的。當然,我們也可以對axios在進行一次封裝,把請求相關的東西都放到里面去,這樣代碼更具有可讀性和維護性。
 首先,我們在src文件夾下面新建一個utils工具文件
 
 在里面新建一個request.js文件,關于請求的信息我們就放到里面進行處理。
 
import axios from "axios";
import { Message, MessageBox } from "element-ui";
import store from "../store";
import { getToken, removeToken} from "./auth";
import { IDPHelper } from "./idp";// 創建axios實例
const service = axios.create({baseURL: process.env.BASE_API, // api的base_urltimeout: 15000,validateStatus: (status) => {return true;}
});// request攔截器
service.interceptors.request.use(config => {if (store.getters.token) {// config.headers['Authorization'] = getToken() // 讓每個請求攜帶自定義token 請根據實際情況自行修改config.headers["token"] = getToken();}return config;},error => {// Do something with request errorconsole.log(error); // for debugPromise.reject(error);}
);// respone攔截器
service.interceptors.response.use(response => {const status = response.status;if (status >= 200 && status < 300) {return response.data;}switch (status) {case 401:MessageBox.confirm("你已被登出,請重新登錄","確定登出",{confirmButtonText: "重新登錄",cancelButtonText: "取消",type: "warning"}).then(() => {removeToken();router.push('/login')});break;case 403:MessageBox.confirm("你無權訪問該頁面,請申請權限再行訪問","系統安全",{confirmButtonText: "回退",cancelButtonText: "繼續留下",type: "warning"}).then(() => {window.history & window.history.back()});break;case 404:case 408:Message({message: "請求資源不存在!",type: "error",duration: 3 * 1000});break;case 500:case 502:case 504:default:Message({message: "服務器繁忙,請稍后重試!",type: "error",duration: 3 * 1000});break;}return Promise.reject("error");},error => {console.log("err" + error); // for debugMessage({message: error.message,type: "error",duration: 3 * 1000});return Promise.reject(error);}
);export default service;
 
使用:
 
                            總結
                            
                                以上是生活随笔為你收集整理的前后端分离,如何解决跨域(代理模式)、路由拦截(进入页面需要登录)以及请求拦截(登录TOKEN失效)等问题(初学者)的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                            
                                如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。