在vue項目中,與后端的數(shù)據(jù)交互只能通過ajxa。在解決用戶權(quán)限問題上,后臺的攔截器可以攔截需要登陸的請求。在vue項目中,我們也可以vue-router的導(dǎo)航守衛(wèi)功能實現(xiàn)
-
場景描述
假設(shè)有一個場景,首頁頁面訪問不需要校驗用戶權(quán)限,因為用戶未登錄無法判斷其權(quán)限。訪問管理后臺頁面時,如果用戶沒有登陸自動跳轉(zhuǎn)到登陸頁面,這種實現(xiàn)效果類似與后臺的攔截器。
在vue項目中,我們?nèi)绾螌崿F(xiàn)這種效果呢。我們可以通過vue-router提供的導(dǎo)航守衛(wèi)功能實現(xiàn)。
-
全局守衛(wèi)
vue-router的導(dǎo)航守衛(wèi)可以是全局的,也可以是某個路由級別的。下面講講全局的導(dǎo)航守衛(wèi)怎么實現(xiàn)
- 首先我們要在登陸的時候存儲用戶是否登陸的標(biāo)志位置(省略了登陸過程的代碼,在此僅展示登陸標(biāo)志的存儲)
// 登陸成功,返回用戶信息
var userinfo = response.data.result;
userinfo.isSignin = true;// 用戶是否是登陸狀態(tài)
that.$store.dispatch("setUserInfo", userinfo);
- 接下來,我們需要在路由表中指出哪些路由需要登陸才能訪問,哪些又不需要登陸。在/router/index.js中,我們可以看出后臺管理模塊和首頁模塊的區(qū)別是,在于后臺管理模塊有個meta: {login_required: true},這個就是路由的元數(shù)據(jù),可以設(shè)置路由的一些私有屬性。這個login_required就是標(biāo)識只有登陸了的用戶才能訪問管理模塊的頁面。
export default new Router({
routes: [
// 首頁模塊
{
path: '/', component: resolve => {require(['../components/home/Home'], resolve)},
children: [
{path: '/', name: 'index', component: resolve => {require(['../components/home/Index'], resolve)},},
{path: 'product1', name: 'product1', component: resolve => {require(['../components/home/Product1'], resolve)},},
{path: 'product2', name: 'product2', component: resolve => {require(['../components/home/Product2'], resolve)},},
{path: 'contact', name: 'contact', component: resolve => {require(['../components/home/Contact'], resolve)},},
// 登錄模塊
{path: 'signin', name: 'signin', component: resolve => {require(['../components/sign/Signin'], resolve)},},
{path: 'signup', name: 'signup', component: resolve => {require(['../components/sign/Signup'], resolve)},},
{path: 'forgetpwd', name: 'forgetpwd', component: resolve => {require(['../components/sign/ForgetPwd'], resolve)},},
{path: 'resetpwd', name: 'resetpwd', component: resolve => {require(['../components/sign/ResetPwd'], resolve)},}
]
},
//后臺管理模塊
{
path: '/manage',meta: {login_required: true}, name: 'manage', component: resolve => {require(['../components/manage/Manage'], resolve)},
}
]
});
- 在存儲了登陸標(biāo)識和標(biāo)識了需要登陸的路由后,接下來我們需要全局的攔截判斷,如果當(dāng)前登陸標(biāo)識為false,并且要訪問的路由是要登陸才能訪問的,那么就拒絕訪問,直接跳轉(zhuǎn)到登錄頁面。在main.js中實現(xiàn)如下:
//權(quán)限驗證
router.beforeEach((to, from, next) => {
//校驗是否登陸了
let isSignin = localStorage.getItem("isSignin");
let matched = to.matched.some((item) => {
return item.meta.login_required;
});
if(isSignin == 'false' && matched){
next('/signin');
}else{
next();
}
});
- 接下來就可以驗證直接訪問/manage是否會跳轉(zhuǎn)的/signin頁面了。
-
組件級別的守衛(wèi)
比如我們需要在某個組件中,當(dāng)前往其它頁面時需要給出提示,提醒會丟失當(dāng)前頁面的內(nèi)容。這種效果我們也可以通過vue-router實現(xiàn)
在某個組件中:
// 離開頁面時
// 與methodes同一級別
beforeRouteLeave(to,from,next) {
var that = this;
let matched = to.matched.some((item) => {
return item.meta.case_not_need_confirm;
});
if(matched || that.notNeedConfirm){//當(dāng)前頁面或者有些頁面不需要提醒
next();
}else{
that.$confirm(that.$t('promotInfo.closePromot'), that.$t('promotInfo.prompt'), {
confirmButtonText: that.$t('btnName.submitBtn'),
cancelButtonText: that.$t('btnName.cancelBtn'),
type: 'warning',
center: true
}).then(() => {
next();
});
}
}
在不需要提醒的路由上,我們可以添加以下元數(shù)據(jù)來表示訪問此頁面不需要提醒。
meta: {case_not_need_confirm: true}
-
總結(jié)
通過以上兩個例子筆者展示了在全局和組件級別實現(xiàn)導(dǎo)航守衛(wèi)的功能,這種效果最終相當(dāng)于后臺的過濾器,這對系統(tǒng)的安全性和可用性有很大幫助。