Vue Router 簡單易上手,能實現大部分的需求。但是,如果在專案裡需要更細緻的控制路由,以實現與其同步的效果,就需要挖掘其文件裡沒詳細提及的內容。第一章為路由元資訊用途挖掘。
路由元資訊用途
(1)驗證使用者身份
大部分專案,除了登入頁、重置密碼頁、使用者協議頁以外,頁面都需要驗證使用者身份進行訪問。使用 Vue Router 可以配合後端進行雙重驗證。
(登入)驗證身份方法:
1、給需要驗證的路由物件新增 meta 欄位,裡面自定義一個代表驗證的欄位:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
meta: {
requiresAuth: true // 新增該欄位,表示進入這個路由是需要登入的
}
}
]
}
]
})
2、在全域性導航鉤子裡驗證 requiresAuth 欄位:
注意事項:
- 使用 beforeEach 在路由變化前驗證。驗證原理是在跳轉前,訪問目標路由物件的 requiresAuth 欄位判斷是否需要驗證使用者身份,如為是,檢測是否有儲存使用者資訊(即使用者登入成功後前端儲存的資訊,例如 token)
- 每個路由都有一個 $route.matched 陣列,包含當前路由的父級路由物件和當前路由物件,在元件中可以通過 this.$route.matched 訪問
- beforeEach 的 to 引數即目標路由物件 $route,to.matched 即是它的路由陣列
- 因此,使用 some 方法,只要路由陣列裡的任意路由物件需要驗證身份,即進行驗證
- 驗證成功跳轉正確頁面;失敗則跳到登入頁,將目標地址附在 url 的 query 裡,登入成功就跳轉到目標地址
router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
if (!auth.loggedIn()) { // 沒登入
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next() // 確保一定要呼叫 next()
}
} else {
next() // 確保一定要呼叫 next()
}
})
3、攔截 http 請求,驗證使用者身份
為了防止本地儲存的 token 過期,需要攔截 http 請求,為每次請求頭加上 token ,然後攔截 http 響應,根據響應內容判斷是否需要跳回登入頁面重新登入。使用 axios 的方法如下:
// http request 攔截器
axios.interceptors.request.use(
config => {
if (auth.loggedIn()) { // 判斷是否存在token,如果存在的話,則每個http header都加上token
config.headers.Authorization = `token ${auth.loggedIn()}`;
}
return config;
},
err => {
return Promise.reject(err);
});
// http response 攔截器
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (error.response) {
switch (error.response.status) {
case 401:
// Unauthorized
// 返回 401 清除token資訊並跳轉到登入頁面
auth.clear();
router.replace({
path: 'login',
query: {
redirect: router.currentRoute.fullPath
}
})
}
}
return Promise.reject(error.response.data) // 返回介面返回的錯誤資訊
});
(2)定義使用者許可權能訪問的頁面
前端檢視許可權,也是配合後端進行某些頁面的隱藏顯示功能。一般應用於綜合的辦公系統,由 IT 部分配賬號,不同部門的人只能看到自己負責的內容,例如行政部不會看到財務資料頁面。
實現方法:
- 與後端商定每個使用者角色對應的 level 級別,以數值表示
- 前端路由每個頁面的 meta 物件新增 level 欄位,值為陣列,裡面是有許可權訪問頁面的 level 數值
- 登入成功,後臺返回使用者 token 的同時,返回其所屬的 level 欄位
- 元件程式碼比較目標頁面的 level 與使用者 level,只顯示包含在目標 level 陣列裡的頁面
- 全域性導航鉤子 beforeEach 裡比較目標頁面的 level 與使用者 level,包含在目標 level 陣列裡則正確跳轉,反之取消跳轉並提示許可權不足
上面第5步是為了防止使用者直接在瀏覽器輸入目標地址
(3)其他內容控制
可以控制顯示路由固定的搭配,例如某個路由地址的 title 是固定的字串、固定的歡迎語、固定的 favicon 等。在元件裡通過 this.$route.meta.xxx 訪問。
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
meta: {
title: '標題',
message: '歡迎您',
requiresAuth: true // 新增該欄位,表示進入這個路由是需要登入的
}
}
]
}
]
})
第二章的內容在此 https://segmentfault.com/a/11...