vue實戰:HTTP路由攔截

vue中有“三霸”:攔截器、路由守衛、導航守衛。
他們都有一個共同的作用(…也可能是唯一的作用) —— 在路由變更前做一次判斷,或取或舍,或添加token、session之類的【頭信息】。

fj

攔截器

我們先看其工作原理:
tp

其基本用法:

Vue.http.interceptors.push((request,next)=>{
	//請求發送前的處理邏輯
	next((response)=>{
		//請求發送後的處理邏輯
		return response;
	})
})

攔截器是一個全局性的處理函數(工具),它的侷限也是“全局”:所有請求都要統一處理,所以用的地方不多 —— 泛用性提示:提示框!

當與服務器進行通信時,我們顯示一個“ 加載中… ”的攔截畫面隔絕用戶進行其他的操作,待處理完成後再去刪除加載畫面。
這裏我們不妨使用UI組件,但是這個不重要,重點是 我們要將攔截器代碼寫在main.js文件裏 ,因爲它是一個全局性方法

Vue.http.interceptors.push((request,next)=>{
	if(request.url.includes('/api/')){
		let modal=window.UIkit.modal.blockUI(`
			<div class="uk-modal-spinner"></div>
			<p class="uk-text-center">加載中...</p>
		`,{
			center:true
		})

		next((response)=>{
			modal.hide();
			return response;
		})
	}
})

這樣在每次向服務器發送請求時就會先在頁面顯示出一個“加載中…”的loading框。

tj

一般我們使用的是【axios】,不會像上面代碼中那樣做攔截 —— axios攔截器分爲request攔截(請求攔截器:響應配置)和response攔截(響應攔截器:處理請求過來的數據)兩種,而且他們一般一起使用!
下面是筆者做的一個項目中爲登錄添加token的示例:

新增文件setaxios.js

export default function setAxios(){   //暴露出去
	axios.interceptors.request.use(config=>{
		if(store.state.token){
			config.header.token=store.state.token   // 配置header
		}
		return config
	},error=>{
		return Promise.reject(error)
	})
	
	axios.interceptors.response.use(response=>{
		if(response.status==200){
			const data=response.data
			if(data.code==-1){
				store.commit('settoken','')
				localStorage.removeItem('token')
				router.replace({path:'/login'})
			}
			return data
		}
		return response
	},error=>{
		return Promise.reject(error)
	})
}

因爲它要全局“被動觸發”,所以我們就可以將上面代碼在main.js文件裏使用:

import setaxios from './setaxios'

setaxios();

tj

配置“路由守衛”

讓我們來到router.js文件中 —— 這裏是“路由”的“聚集地”。

其實每個router對象中都有一個meta屬性(這可能是因爲編譯成HTML的緣故吧):它有一個字段requireAuth

{
	path:'xxx',
	name:'xxx',
	meta:{
		requireAuth:true
	},
	component:()=>import('./xx/xxx')
},
//...

有了這個字段且值爲true時,我們就默認爲這個路由頁面需要有登錄權限的。
所以,
配置完上面,我們要回到main.js文件:在這裏(new Vue()之外)添加

導航守衛

router.beforeEach((to,from,next)=>{
	//無論是刷新還是跳轉路由,第一個進入的就是這個路由前置鉤子函數
	store.commit('settoken',localStorage.getItem('token'))
	if(to.meta.requireAuth){
		if(store.state.token){
			next()
		}else{
			next({
				path:'/login',
				query:{redirect:to.fullPath}
			})
		}
	}else{
		next()
	}
})

這樣,我們就可以在login.vue頁面判斷跳轉 —— 實現“再次進去返回到原頁面而不是跳轉到首頁”的功能:

if(this.$route.query.redirect){
	this.$router.replace({path:this.$route.query.redirect})
}else{
	this.$router.replace({path:'/xxx/xxx'})
}

tj

導航守衛還可以用在組件內部:比如前面提到的loading

<div v-if="state==loading">
	is loading...
</div>
<div>
	<h1>{{userInfo.name}}</h1>
</div>

//js代碼
data(){
	return{
		state:'loading',
		userInfo:{}
	}
},
mounted(){
	this.init();
}beforeRouteUpdate(to,from,next){
	this.state='loading'
	this.init()
	next()
},
methods:{
	init(){
		fetch(`/api/usr/${this.$route.params.id}`)
			.then((res)=>res.json)
			.then((data)=>{
				this.state='';
				this.userInfo=data;
			});
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章