Vue - 路由守衛(wèi)(路由的生命周期)

路由守衛(wèi)是什么?

官方解釋:

“導(dǎo)航”表示路由正在發(fā)生改變。正如其名,vue-router提供的導(dǎo)航守衛(wèi)主要用來通過跳轉(zhuǎn)或取消的方式守衛(wèi)導(dǎo)航。有多種機(jī)會(huì)植入路由導(dǎo)航過程中:全局的, 單個(gè)路由獨(dú)享的, 或者組件級(jí)的。

簡(jiǎn)單的說,導(dǎo)航守衛(wèi)就是路由跳轉(zhuǎn)過程中的一些鉤子函數(shù)。路由跳轉(zhuǎn)是一個(gè)大的過程,這個(gè)大的過程分為跳轉(zhuǎn)前中后等等細(xì)小的過程,在每一個(gè)過程中都有一函數(shù),這個(gè)函數(shù)能讓你操作一些其他的事兒,這就是導(dǎo)航守衛(wèi)。類似于組件生命周期鉤子函數(shù)

路由守衛(wèi)分類

【1】全局守衛(wèi):是指路由實(shí)例上直接操作的鉤子函數(shù),特點(diǎn)是所有路由配置的組件都會(huì)觸發(fā),直白點(diǎn)就是觸發(fā)路由就會(huì)觸發(fā)這些鉤子函數(shù)

  • beforeEach(to,from, next)
  • beforeResolve(to,from, next)
  • afterEach(to,from)

【2】路由守衛(wèi):是指在單個(gè)路由配置的時(shí)候也可以設(shè)置的鉤子函數(shù)

  • beforeEnter(to,from, next)

【3】組件守衛(wèi):是指在組件內(nèi)執(zhí)行的鉤子函數(shù),類似于組件內(nèi)的生命周期,相當(dāng)于為配置路由的組件添加的生命周期鉤子函數(shù)。

  • beforeRouteEnter(to,from, next)
  • beforeRouteUpdadte(to,from, next)
  • beforeRouteLeave(to,from, next)

路由守衛(wèi)回調(diào)參數(shù)介紹

to:即將要進(jìn)入的目標(biāo)路由對(duì)象;

from:即將要離開的路由對(duì)象;

next:涉及到next參數(shù)的鉤子函數(shù),必須調(diào)用next()方法來resolve這個(gè)鉤子,否則路由會(huì)中斷在這,不會(huì)繼續(xù)往下執(zhí)行

  • next():進(jìn)行管道中的下一個(gè)鉤子。如果全部鉤子執(zhí)行完了,則導(dǎo)航的狀態(tài)就是confirmed(確認(rèn)的)。
  • next( false )中斷當(dāng)前的導(dǎo)航。如果瀏覽器的 URL 改變了 (可能是用戶手動(dòng)或者瀏覽器后退按鈕),那么 URL 地址會(huì)重置到from路由對(duì)應(yīng)的地址。
  • next( ' / ')或者next({ paht:' / ' }):跳轉(zhuǎn)到一個(gè)不同的地址。當(dāng)前的導(dǎo)航被中斷,然后進(jìn)行一個(gè)新的導(dǎo)航??蓚鬟f的參數(shù)可以是router-link標(biāo)簽中的to屬性參數(shù)或router.push中的選項(xiàng)
  • next( error ):如果傳入next的參數(shù)是一個(gè)Error實(shí)例,則導(dǎo)航會(huì)被終止且該錯(cuò)誤會(huì)被傳遞給router.onError()注冊(cè)過的回調(diào)。

路由守衛(wèi)詳解

【1】全局前置守衛(wèi)(beforeEach): 在路由跳轉(zhuǎn)前觸發(fā),這個(gè)鉤子作用主要是用于登錄驗(yàn)證,也就是路由還沒跳轉(zhuǎn)提前告知,以免跳轉(zhuǎn)了再通知就為時(shí)已晚。

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

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

【2】全局解析守衛(wèi)(beforeResolve): 這個(gè)鉤子和beforeEach類似,也是路由跳轉(zhuǎn)前觸發(fā),區(qū)別是在導(dǎo)航被確認(rèn)之前,同時(shí)在所有組件內(nèi)守衛(wèi)和異步路由組件被解析之后,即在 beforeEach 和 組件內(nèi)beforeRouteEnter 之后,afterEach之前調(diào)用。

【3】全局后置鉤子(afterEach): 和beforeEach相反,它是在路由跳轉(zhuǎn)完成后觸發(fā),它發(fā)生在beforeEach和beforeResolve之后,beforeRouteEnter(組件內(nèi)守衛(wèi))之前。這些鉤子不會(huì)接受next函數(shù)也不會(huì)改變導(dǎo)航本身

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

【4】路由獨(dú)享守衛(wèi)(beforeEnter): 和beforeEach完全相同,如果兩個(gè)都設(shè)置了,beforeEnter則在beforeEach之后緊隨執(zhí)行。在路由配置上直接定義beforeEnter守衛(wèi)

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

【5】組件內(nèi)的守衛(wèi):

<template>
  ...
</template>
<script>
export default{
  data(){
    //...
  },
  beforeRouteEnter (to, from, next) {
    // 在渲染該組件的對(duì)應(yīng)路由被 confirm 前調(diào)用
    // 不!能!獲取組件實(shí)例 `this`
    // 因?yàn)楫?dāng)守衛(wèi)執(zhí)行前,組件實(shí)例還沒被創(chuàng)建
  },
  beforeRouteUpdate (to, from, next) {
    // 在當(dāng)前路由改變,但是該組件被復(fù)用時(shí)調(diào)用
    // 舉例來說,對(duì)于一個(gè)帶有動(dòng)態(tài)參數(shù)的路徑 /foo/:id,在 /foo/1 和 /foo/2 之間跳轉(zhuǎn)的時(shí)候,
    // 由于會(huì)渲染同樣的 Foo 組件,因此組件實(shí)例會(huì)被復(fù)用。而這個(gè)鉤子就會(huì)在這個(gè)情況下被調(diào)用。
    // 可以訪問組件實(shí)例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 導(dǎo)航離開該組件的對(duì)應(yīng)路由時(shí)調(diào)用
    // 可以訪問組件實(shí)例 `this`
  }
}
</script>
<style>
  ...
</style>

1. beforeRouteEnter:該鉤子在全局守衛(wèi)beforeEach和獨(dú)享守衛(wèi)beforeEnter之后,全局beforeResolve和全局afterEach之前調(diào)用,要注意的是該守衛(wèi)內(nèi)訪問不到組件的實(shí)例,也就是this為undefined。因?yàn)樗诮M件生命周期beforeCreate階段觸發(fā),此時(shí)的新組件還沒有被創(chuàng)建。在這個(gè)鉤子函數(shù)中,可以通過傳一個(gè)回調(diào)給 next來訪問組件實(shí)例。在導(dǎo)航被確認(rèn)的時(shí)候執(zhí)行回調(diào),并且把組件實(shí)例作為回調(diào)方法的參數(shù)。

beforeRouteEnter (to, from, next) {
  next(vm => {
    // 通過 `vm` 訪問組件實(shí)例
  })
}

2. beforeRouteUpdadte:在當(dāng)前路由改變時(shí),并且該組件被復(fù)用時(shí)調(diào)用,可以通過this訪問實(shí)例。

3. beforeRouteLeave:導(dǎo)航離開該組件的對(duì)應(yīng)路由時(shí)調(diào)用,可以訪問組件實(shí)例this。這個(gè)離開守衛(wèi)通常用來禁止用戶在還未保存修改前突然離開。該導(dǎo)航可以通過next( false )來取消。

beforeRouteLeave (to, from , next) {
  const answer = window.confirm('Do you really want to leave? you have unsaved changes!')
  if (answer) {
    next()
  } else {
    next(false)
  }
}

完整的導(dǎo)航解析流程

  1. 觸發(fā)進(jìn)入其它路由
  2. 調(diào)用要離開路由的組件守衛(wèi)beforeRouteLeave
  3. 調(diào)用全局的前置守衛(wèi)beforeEach
  4. 在重用的組件里調(diào)用 beforeRouteUpdate
  5. 在路由配置里調(diào)用 beforeEnter
  6. 解析異步路由組件
  7. 在將要進(jìn)入的路由組件中調(diào)用beforeRouteEnter
  8. 調(diào)用全局的解析守衛(wèi)beforeResolve
  9. 導(dǎo)航被確認(rèn)
  10. 調(diào)用全局的后置鉤子afterEach。
  11. 觸發(fā) DOM 更新mounted
  12. 執(zhí)行beforeRouteEnter守衛(wèi)中傳給 next的回調(diào)函數(shù)。

文章每周持續(xù)更新,可以微信搜索「 前端大集錦 」第一時(shí)間閱讀,回復(fù)【視頻】【書籍】領(lǐng)取200G視頻資料和30本PDF書籍資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容