vue路由鉤子函數(shù)有2種,分別為:1、全局守衛(wèi)(全局鉤子函數(shù)),指的是“index.js”中的router對象;2、路由守衛(wèi)(針對單個路由鉤子函數(shù));3、組件守衛(wèi)(組件級鉤子函數(shù)),是定義在路由組件內(nèi)部的守衛(wèi)。
本教程操作環(huán)境:windows7系統(tǒng)、vue2.9.6版,DELL G3電腦。
vue-router
的 鉤子函數(shù) ,其實說的就是 導(dǎo)航守衛(wèi) 。
引用官網(wǎng)的話
“導(dǎo)航” 表示路由正在發(fā)生改變。
vue-router
提供的導(dǎo)航守衛(wèi)主要用來通過 跳轉(zhuǎn) 或 取消 的方式 守衛(wèi)導(dǎo)航 。有多種機會植入路由導(dǎo)航過程中:全局的, 單個路由獨享的, 或者組件級的。
也就是:全局守衛(wèi)(全局鉤子函數(shù))、路由守衛(wèi)(針對單個路由鉤子函數(shù))、組件守衛(wèi)(組件級鉤子函數(shù))。
代碼演示環(huán)境搭建
先簡單搭建一下環(huán)境
index.js
import { createRouter, createWebHashHistory } from 'vue-router'; const router = createRouter({ history: createWebHashHistory(), routes: [ { path: '/a', component: () => import('../components/A.vue'), }, { path: '/b', component: () => import('../components/B.vue'), }, { path: '/c', component: () => import('../components/C.vue'), }, ], }); export default router;
main.js
// index.js import router from "./router"; createApp(App).use(router).mount("#app");
頁面A
<template> <div> <h1>我是頁面A啊</h1> <comp></comp> </div> </template>
頁面B
<template> <div> <h1>我是頁面B啊</h1> <comp></comp> </div> </template>
頁面C
<template> <div> <h1>我是頁面C啊</h1> <comp></comp> </div> </template>
通用組件
<template> <div>我是公用組件啊</div> </template>
當(dāng)前頁面是這樣的,有點丑,湊活看吧,咱也不是來學(xué)習(xí) css
的
全局守衛(wèi)
顧名思義,是要定義在全局的,也就是我們 index.js
中的 router
對象。
beforeEach
全局前置守衛(wèi),在路由跳轉(zhuǎn)前觸發(fā),它在 每次導(dǎo)航 時都會觸發(fā)。
通過 router.beforeEach
注冊一個全局前置守衛(wèi)。
參數(shù)
beforeEach
全局前置守衛(wèi)接收三個參數(shù)
- to: Route: 即將要進入的目標(biāo)路由對象
- from: Route: 當(dāng)前導(dǎo)航正要離開的路由對象
- next: Function: 一定要調(diào)用該方法不然會阻塞路由。
注意: next
參數(shù)可以不添加,但是一旦添加,則必須調(diào)用一次,否則路由跳轉(zhuǎn)等會停止。
next()
方法的幾種情況
- next(): 進行管道中的下一個鉤子。
- next(false): 中斷當(dāng)前的導(dǎo)航?;氐?
from
路由對應(yīng)的地址。 - next(’/’) 或者 next({ path: ‘/’ }): 跳轉(zhuǎn)到一個不同的地址,可傳遞的參數(shù)與
router.push
中選項一致。 - next(error): 導(dǎo)航終止,且該錯誤會被傳遞給
router.onError()
注冊過的回調(diào)。
我們把前兩個參數(shù)打印出來看一下,里面包含路徑,參數(shù),元信息等內(nèi)容。
返回值
- false:取消當(dāng)前的導(dǎo)航。
- null,undefined,true或者直接return:調(diào)用下一個導(dǎo)航守衛(wèi)。
定義多個守衛(wèi)
全局前置守衛(wèi)可以定義多個,根據(jù)創(chuàng)建順序調(diào)用。在所有守衛(wèi)完成之前導(dǎo)航一直處于等待中。
下面這個例子中我們就定義了兩個 beforeEach
全局前置守衛(wèi)??梢钥吹剑挥性趦擅胍院蠓謩e打印出兩條日志后才進行頁面的跳轉(zhuǎn)。
除了 beforeEach
全局前置守衛(wèi)之外,其他的全局守衛(wèi)都可以定義多個,并且在所有守衛(wèi)完成之前導(dǎo)航一直處于等待中,其他的鉤子函數(shù)就不進行演示了。
beforeResolve
全局解析守衛(wèi),在路由跳轉(zhuǎn)前,所有 組件內(nèi)守衛(wèi) 和 異步路由組件 被解析之后觸發(fā),它同樣在 每次導(dǎo)航 時都會觸發(fā)。
通過 router.beforeResolve
注冊一個全局解析守衛(wèi)。
router.beforeResolve((to, from, next) => { next(); })
回調(diào)參數(shù),返回值和 beforeEach
一樣。也可以定義多個全局解析守衛(wèi)。
afterEach
全局后置鉤子,它發(fā)生在路由跳轉(zhuǎn)完成后,beforeEach
和 beforeResolve
之后,beforeRouteEnter
(組件內(nèi)守衛(wèi))之前。它同樣在 每次導(dǎo)航 時都會觸發(fā)。
通過 router.afterEach
注冊一個全局后置鉤子。
這個鉤子的兩個參數(shù)和 beforeEach
中的 to
和 from
一樣。然而和其它全局鉤子不同的是,這些鉤子不會接受 next
函數(shù),也不會改變導(dǎo)航本身。
路由守衛(wèi)
顧名思義,就是跟路由相關(guān)的鉤子,我們的路由守衛(wèi)只有一個,就是 beforeEnter
。
beforeEnter
需要在路由配置上定義 beforeEnter
守衛(wèi),此守衛(wèi)只在進入路由時觸發(fā),在 beforeEach
之后緊隨執(zhí)行,不會在 params
、query
或 hash
改變時觸發(fā)。
beforeEnter
路由守衛(wèi)的參數(shù)是 to
、from
、next
,同 beforeEach
一樣。
組件守衛(wèi)
顧名思義,是定義在路由組件內(nèi)部的守衛(wèi)。
beforeRouteEnter
路由進入組件之前調(diào)用,該鉤子在全局守衛(wèi) beforeEach
和路由守衛(wèi) beforeEnter
之后,全局 beforeResolve
和全局 afterEach
之前調(diào)用。
參數(shù)包括 to
,from
,next
。
該守衛(wèi)內(nèi)訪問不到組件的實例,也就是 this
為 undefined
,也就是他在 beforeCreate
生命周期前觸發(fā)。
beforeRouteUpdate
對于 beforeRouteUpdate
來說,this
已經(jīng)可用了,所以給 next
傳遞回調(diào)就沒有必要了。
beforeRouteLeave
對于 beforeRouteLeave
來說,this
已經(jīng)可用了,所以給 next
傳遞回調(diào)就沒有必要了。
總結(jié)
完整的導(dǎo)航解析流程
- 導(dǎo)航被觸發(fā)。
- 在失活的組件里調(diào)用
beforeRouteLeave
守衛(wèi)。- 調(diào)用全局的
beforeEach
守衛(wèi)。- 在重用的組件里調(diào)用
beforeRouteUpdate
守衛(wèi)。- 在路由配置里調(diào)用
beforeEnter
。- 解析異步路由組件。
- 在被激活的組件里調(diào)用
beforeRouteEnter
。- 調(diào)用全局的
beforeResolve
守衛(wèi)。- 導(dǎo)航被確認(rèn)。
- 調(diào)用全局的
afterEach
鉤子。- 觸發(fā)
DOM
更新。- 調(diào)用
beforeRouteEnter
守衛(wèi)中傳給next
的回調(diào)函數(shù),創(chuàng)建好的組件實例會作為回調(diào)函數(shù)的參數(shù)傳入。
上面是官方給出的答案,現(xiàn)在我們用流程圖來直觀的展示一下。