1. 程式人生 > 程式設計 >詳解vue-router的導航鉤子(導航守衛)

詳解vue-router的導航鉤子(導航守衛)

在做vue專案的時候,要求使用者在頁面訪問前先登入,或在離開頁面前發出提醒。vue官方提供的路由管理器 vue-router 提供的導航鉤子,通過跳轉或取消的方式守衛導航。以下總結了路由鉤子函式的使用方法和一些使用場景。

一、全域性守衛

router.beforeEach 路由改變前的鉤子

const router = new VueRouter({ ... })

router.beforeEach((to,from,next) => {
 ... ...
})

其中:

  • to:將要訪問的路徑
  • from:代表從哪個路徑跳轉來的
  • next:是一個函式,表示放行。有如下幾種呼叫方式
    • next():如果一起正常,則呼叫該方法進入下一個鉤子;
    • next(false):中斷當前導航,即路由地址不發生變化;
    • next('/xxx') 或 next({path: '/xxx'}):強制跳轉到指定路徑;
    • next(error):如果傳入的是一個Error例項,則導航會被中斷且該錯誤會被傳遞給 router.onError() 註冊過的回撥。

使用:

使用該函式,一定要呼叫 next(),否則鉤子函式不能 resolve;

該方法比較常用於:驗證使用者訪問許可權。

比如:一個系統需要先驗證使用者是否登入,如果登入了就可以訪問,否則直接跳轉到登入頁面。具體實現如下:

import Vue from 'vue'
import VueRouter from 'vue-router'
import { getToken } from '@Utils/session.utils' // 登入使用者的token
import Login from '../pages/Login.vue' //引入登入頁
const Home = () => import('../pages/Home.vue') //引入首頁

Vue.use(VueRouter) // 全域性注入router

// 配置路由引數
const routes = [
 { path: '/login',name: 'login',component: Login },{ path: '/home',name: 'home',component: Home }
]

const router = new VueRouter({
 routes
})

// 全域性掛載路由導航守衛:驗證使用者是否登入
router.beforeEach((to,next) => {
 if (to.name !== 'login' && !getToken()) next('/login') // 如果使用者不是訪問登入頁且沒有登入,則強制跳轉到登入頁
 else next()
})

export default router

router.beforeResolve 在導航被確認之前,同時在所有元件內守衛和非同步路由元件被解析之後,該鉤子函式就被呼叫。
該方法我在專案中暫時還未使用到,具體使用場景歡迎大家補充 :)

router.afterEach 路由改變後的鉤子

router.afterEach((to,from) => {
 ... ...
})

該方法同全域性前置守衛 router.beforeEach 不同的是少了 next() 函式,也不會改變導航本身。

使用場景:

路由切換,將頁面的滾動位置返回到頂部。

例如:一個頁面比較長,當滾動到某個位置後切換路由,這時跳轉的頁面滾動條位置預設是前一個頁面離開時停留的位置,可以通過該鉤子函式將滾動條位置重置。

// 切換路由,頁面返回到頂部
router.afterEach((to,from) => {
 window.scrollTo(0,0)
})

二、路由獨享的守衛

beforeEnter 對某個路由的單獨守衛,在路由配置上直接定義

const routes = [
 { path: '/login',{ 
  path: '/home',component: Home,beforeEnter: (to,next) => {
   ... ...
  }
 }
]

const router = new VueRouter({
 routes
})

使用:

該方法的引數使用同全域性前置守衛 router.beforeEach 是一樣的;
例如:根據登入使用者的不同角色,展示不同的模組;或者給指定路由元件單獨新增動畫。

import Vue from 'vue'
import VueRouter from 'vue-router'
import { getUserRole } from '@Utils/session.utils' // 登入使用者的角色

const UserCenter = () => import('../pages/UserCenter.vue')

const routes = [
 ... ...
 { 
  path: '/usercenter',name: 'usercenter',component: UserCenter,next) => {
   if(getUserRole() === 'admin') next('/admincenter')
   else next()
  }
 }
]

三、元件內的守衛

beforeRouteEnter(to,next) 在進入當前元件對應的路由前呼叫

export default {
 data() { ... },beforeRouteEnter(to,next) {
  ... ...
 }
}

注意:

該函式內不能訪問當前元件例項 this,因為函式在對應路由被 comfirm 前呼叫,此時將要渲染的元件例項還沒被建立;

可以通過給 next 傳遞一個回撥來訪問元件例項,即把元件例項 vm 作為回撥方法的引數;該回調的執行在 mounted 後面;

beforeRouteEnter (to,next) {
 next(vm => {
  // 通過 vm 來訪問元件例項
 })
}

beforeRouteEnter 是支援給 next 傳遞迴調的唯一守衛。

使用場景:

例如:從一個列表頁進入到詳情頁,然後再返回到列表頁,要求保留離開列表頁之前訪問的資料及滾動位置,從其他頁面重新進入列表頁,獲取最新的資料。具體實現請點這裡
beforeRouteUpdate(to,next) 在當前路由改變,但是該元件被複用時呼叫

beforeRouteUpdate (to,next) {
 ... ...
}

注:

該函式內可以訪問當前元件例項 this

例如:在一個帶有動態引數的路徑 /detail/:id,在 /detail/aaa 和 /detail/bbb 之間跳轉的時候,因為兩個路由渲染的是同個 Detail 元件,因此原來的元件例項會被複用(比起銷燬再建立,複用則會更加高效),在這種情況下這個鉤子會被呼叫,而元件的生命週期鉤子不會再被呼叫。

beforeRouteLeave(to,next) 在離開當前元件對應的路由前呼叫

beforeRouteLeave (to,next) {
 ... ...
}

注:

  • 該函式內可以訪問當前元件例項 this;
  • 比如:使用者在當前頁面有還未儲存的內容時突然離開,阻止頁面跳轉並給出提示,或者在使用者離開時清除或儲存一些資訊等。

四、完整的導航解析流程

  • 導航被觸發;
  • 在失活的元件裡呼叫 beforeRouteLeave 守衛;
  • 呼叫全域性的 beforeEach 守衛;
  • 在重用的元件裡呼叫 beforeRouteUpdate 守衛 (2.2+);
  • 在路由配置裡呼叫 beforeEnter;
  • 解析非同步路由元件;
  • 在被啟用的元件裡呼叫 beforeRouteEnter;
  • 呼叫全域性的 beforeResolve 守衛 (2.5+);
  • 導航被確認;
  • 呼叫全域性的 afterEach 鉤子;
  • 觸發 DOM 更新;
  • 呼叫 beforeRouteEnter 守衛中傳給 next 的回撥函式,建立好的元件例項會作為回撥函式的引數傳入。

其實常用的也就那麼幾個,理解了其用法,路由導航的解析流程也就明瞭了。

五、附:使用 watch 監測路由變化

除了使用鉤子函式外,我們也可以使用 watch 來監聽 $route 物件,然後根據路由引數的變化來進行響應。

<template>
 <div id=``"app"``>
  <keep-alive>
   <router-view/>
  </keep-alive>
 </div>
</template>

<script>
 export default {
  name: 'App',watch: {
   '$route' (to,from) {
    // 對路由變化作出響應...
   }
  }
 }
</script>

到此這篇關於詳解vue-router的導航鉤子(導航守衛)的文章就介紹到這了,更多相關vue-router 導航鉤子內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!