Vue Router 路由守衛(導航守衛)


一、什么是導航守衛

1、官方的定義

提供的導航守衛主要用來通過跳轉或取消的方式守衛導航。有多種機會植入路由導航過程中:全局的, 單個路由獨享的, 或者組件級的。

2、自己的理解

導航守衛就是路由跳轉過程中的一些鈎子函數,再直白點路由跳轉是一個大的過程,這個大的過程分為跳轉前中后等等細小的過程,在每一個過程中都有一函數,這個函數能讓你操作一些其他的事兒的時機,比如跳轉前是否驗證登錄等,這就是導航守衛。

二、使用導航守衛

1、安裝包

npm導入
npm install vue-router --save

cnpm淘寶鏡像導入
cnpm install vue-router --save
如果沒有安裝淘寶鏡像需要先安裝
npm install -g cnpm --registry=https://registry.npm.taobao.org

2、全局守衛

是指路由實例上直接操作的鈎子函數,他的特點是所有路由配置的組件都會觸發,直白點就是觸發路由就會觸發這些鈎子函數。鈎子函數按執行順序包括beforeEach、beforeResolve(2.5+)、afterEach三個

beforeEach:

在路由跳轉前觸發,參數包括to,from,next(參數會單獨介紹)三個,這個鈎子作用主要是用於登錄驗證,也就是路由還沒跳轉提前告知,以免跳轉了再通知就為時已晚。

beforeResolve(2.5+)

這個鈎子和beforeEach類似,也是路由跳轉前觸發,參數也是to,from,next三個,和beforeEach區別官方解釋為:

區別是在導航被確認之前,同時在所有組件內守衛和異步路由組件被解析之后,解析守衛就被調用。
即在 beforeEach 和 組件內beforeRouteEnter 之后,afterEach之前調用。

afterEach:

和beforeEach相反,他是在路由跳轉完成后觸發,參數包括to,from沒有了next(參數會單獨介紹),他發生在beforeEach和beforeResolve之后,beforeRouteEnter(組件內守衛,后講)之前。

他們的使用如下:

router.beforeEach((to, from, next) => {
  //to 將要訪問的路徑
  //from 代表從哪個路徑跳轉而來
  //next 是一個函數,表示放行
  // next() 放行  next('/login') 強制跳轉
})

小案例:

比如我們的后台管理系統,基本上都是需要登錄后才能操作的,所以路由跳轉前先判斷是否登錄,如果未登錄狀態就強制跳轉到登錄頁,代碼如下
router 模塊

import Vue from "vue";
import VueRouter from "vue-router";
import Login from "../components/Login";
import Home from "../components/Home";
import Welcome from "../components/Welcome";
import User from "../components/User/User";


Vue.use(VueRouter);
const router = new VueRouter({
  routes: [
    { path: "/", redirect: "/login" },
    { path: "/login", component: Login },
    {
      path: "/home", component: Home,
      redirect: 'welcome',
      children: [
        { path: '/welcome', component: Welcome },
        { path: '/users', component: User },
      ]
    }
  ]
});
//掛載路由導航守衛,控制頁面訪問權限

router.beforeEach((to, from, next) => {
  if (to.path === '/login') return next();
  //獲取token
  const tokenStr = window.sessionStorage.getItem('token')
  if (!tokenStr) return next('/login')
  next()
})

export default router;

3、單個路由獨享

是指在單個路由配置的時候也可以設置的鈎子函數,其位置就是下面示例中的位置,也就是像Foo這樣的組件都存在這樣的鈎子函數。目前他只有一個鈎子函數beforeEnter。

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})

beforeEnterbeforeEach 完全相同,如果都設置則在beforeEach之后緊隨執行,參數to、from、next

小案例

當只有進入某個路由時,才需要驗證,使用路由元信息
在路由配置中加入 meta

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

router.beforeEach((to, from, next) => {
  if (to.matched.some(record => record.meta.requiresAuth)) {
    // this route requires auth, check if logged in
    // if not, redirect to login page.
    if (!auth.loggedIn()) {
      next({
        path: '/login',
        query: { redirect: to.fullPath }
      })
    } else {
      next()
    }
  } else {
    next() // 確保一定要調用 next()
  }
})

4、組件級

是指在組件內執行的鈎子函數,類似於組件內的生命周期,相當於為配置路由的組件添加的生命周期鈎子函數。鈎子函數按執行順序包括beforeRouteEnter、beforeRouteUpdate (2.2+)、beforeRouteLeave三個,執行位置如下:

<template>
  ...
</template>
export default{
  data(){
    //...
  },
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對應路由被 confirm 前調用
    // 不!能!獲取組件實例 `this`
    // 因為當守衛執行前,組件實例還沒被創建
  },
  beforeRouteUpdate (to, from, next) {
    // 在當前路由改變,但是該組件被復用時調用
    // 舉例來說,對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,
    // 由於會渲染同樣的 Foo 組件,因此組件實例會被復用。而這個鈎子就會在這個情況下被調用。
    // 可以訪問組件實例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導航離開該組件的對應路由時調用
    // 可以訪問組件實例 `this`
  }
}
<style>
  ...
</style>

beforeRouteEnter

路由進入之前調用,參數包括to,from,next。該鈎子在全局守衛beforeEach和獨享守衛beforeEnter之后,全局beforeResolve和全局afterEach之前調用,要注意的是該守衛內訪問不到組件的實例,也就是this為undefined,也就是他在beforeCreate生命周期前觸發。在這個鈎子函數中,可以通過傳一個回調給 next來訪問組件實例。在導航被確認的時候執行回調,並且把組件實例作為回調方法的參數,可以在這個守衛中請求服務端獲取數據,當成功獲取並能進入路由時,調用next並在回調中通過 vm訪問組件實例進行賦值等操作,(next中函數的調用在mounted之后:為了確保能對組件實例的完整訪問)。

beforeRouteEnter (to, from, next) {
  // 這里還無法訪問到組件實例,this === undefined
  next( vm => {
    // 通過 `vm` 訪問組件實例
  })
}

beforeRouteUpdate (v 2.2+)

在當前路由改變時,並且該組件被復用時調用,可以通過this訪問實例。參數包括to,from,next。可能有的同學會疑問,what is 路由改變 or what is 組件被復用?

對於一個帶有動態參數的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉的時候,組件實例會被復用,該守衛會被調用
當前路由query變更時,該守衛會被調用

beforeRouteLeave

導航離開該組件的對應路由時調用,可以訪問組件實例this,參數包括to,from,next。

三、總結

全局路由鈎子:

beforeEach(to,from, next)、beforeResolve(to,from, next)、afterEach(to,from);

獨享路由鈎子:

beforeEnter(to,from, next);

組件內路由鈎子:

beforeRouteEnter(to,from, next)、beforeRouteUpdate(to,from, next)、beforeRouteLeave(to,from, next)

導航守衛回調參數

to:目標路由對象;

from:即將要離開的路由對象;

next:他是最重要的一個參數,他相當於佛珠的線,把一個一個珠子逐個串起來。以下注意點務必牢記:

1.但凡涉及到有next參數的鈎子,必須調用next() 才能繼續往下執行下一個鈎子,否則路由跳轉等會停止。

2.如果要中斷當前的導航要調用next(false)。如果瀏覽器的 URL 改變了 (可能是用戶手動或者瀏覽器后退按鈕),那么 URL 地址會重置到from路由對應的地址。(主要用於登錄驗證不通過的處理)

3.當然next可以這樣使用,next('/') 或者 next({ path: '/' }): 跳轉到一個不同的地址。意思是當前的導航被中斷,然后進行一個新的導航。可傳遞的參數與router.push中選項一致。

4.在beforeRouteEnter鈎子中next((vm)=>{})內接收的回調函數參數為當前組件的實例vm,這個回調函數在生命周期mounted之后調用,也就是,他是所有導航守衛和生命周期函數最后執行的那個鈎子。

5.next(error): (v2.4.0+) 如果傳入 next 的參數是一個 Error 實例,則導航會被終止且該錯誤會被傳遞給 router.onError() 注冊過的回調。

當點擊切換路由時:

beforeRouterLeave-->beforeEach-->beforeEnter-->beforeRouteEnter-->beforeResolve-->afterEach-->beforeCreate-->created-->beforeMount-->mounted-->beforeRouteEnter的next的回調

當路由更新時:

beforeRouteUpdate
官方文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM