你可能不清楚的 Vue Router 深度用法(一)
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) // 返回介面返回的錯誤資訊 });
前端檢視許可權,也是配合後端進行某些頁面的隱藏顯示功能。一般應用於綜合的辦公系統,由 IT 部分配賬號,不同部門的人只能看到自己負責的內容,例如行政部不會看到財務資料頁面。
實現方法:
- 前端路由每個頁面的 meta 物件新增 level 欄位,設定 0 ~ n 級別
- 登入成功,後臺返回使用者 token 的同時,返回其所屬的 level 欄位
- 元件程式碼比較目標頁面的 level 與使用者 level,只顯示目標 level 小於等於使用者 level 的頁面
- 全域性導航鉤子 beforeEach 裡比較目標頁面的 level 與使用者 level,小於等於目標 level 則正確跳轉,反之取消跳轉並提示許可權不足
上面第4步是為了防止使用者直接在瀏覽器輸入目標地址
(2)其他內容控制
可以控制顯示路由固定的搭配,例如某個路由地址的 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 // 新增該欄位,表示進入這個路由是需要登入的 } } ] } ] })