你可能不清楚的 Vue Router 深度用法(一)

weixin_34127717發表於2019-02-16
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 部分配賬號,不同部門的人只能看到自己負責的內容,例如行政部不會看到財務資料頁面。

實現方法:

  1. 與後端商定每個使用者角色對應的 level 級別,以數值表示
  2. 前端路由每個頁面的 meta 物件新增 level 欄位,值為陣列,裡面是有許可權訪問頁面的 level 數值
  3. 登入成功,後臺返回使用者 token 的同時,返回其所屬的 level 欄位
  4. 元件程式碼比較目標頁面的 level 與使用者 level,只顯示包含在目標 level 陣列裡的頁面
  5. 全域性導航鉤子 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...

相關文章