深入理解 Vue Router

在前端單頁應用(SPA)中,路由是連接用户操作與頁面展示的核心橋樑。Vue Router 作為 Vue 官方的路由管理器,提供了豐富的功能和靈活的配置。本文將圍繞“路由模式”、“router 與 route 的區別”、“導航守衞的種類”以及“完整的導航解析流程”四個方面,帶你深入理解 Vue Router 的工作機制。

一、路由模式:hash 與 history 的實現原理

Vue Router 支持兩種主流的路由模式:hash 模式 和 history 模式。它們的底層實現機制不同,決定了使用方式和部署時的差異。

1. hash 模式

hash 模式是基於 URL 中 # 後面的內容變化實現的。瀏覽器不會將 # 後的部分發送到服務器,因此不會觸發頁面刷新。

  • 監聽機制:通過監聽 window.onhashchange 事件,捕獲 hash 值的變化。
  • 優點:
    • 兼容性好,支持 IE 及以下版本。
    • 部署簡單,刷新頁面不會 404。
  • 缺點:
    • URL 不夠美觀,帶有 # 符號。

2. history 模式

history 模式依賴 HTML5 提供的 pushStatereplaceState API,可以在不刷新頁面的情況下修改 URL。

  • 監聽機制:通過監聽 popstate 事件,捕獲瀏覽器前進/後退操作。
  • 優點:
    • URL 更乾淨,沒有 #
  • 缺點:
    • 需要後端配合,刷新頁面或直接訪問子路徑時,需將所有請求重定向到入口文件(如 index.html),否則會返回 404。
    • 對低版本瀏覽器支持不佳。

二、router 與 route 的區別

在 Vue 組件中,我們常常使用 this.$routerthis.$route,但它們代表的含義完全不同:

router

  • 是 Vue Router 的實例對象,包含整個路由的配置和控制方法。
  • 常用方法:
    • this.$router.push():跳轉到指定路由,添加一條歷史記錄。
    • this.$router.replace():替換當前路由,不添加歷史記錄。
    • this.$router.go(n):前進或後退 n 步。

route

  • 是當前激活路由的信息對象,包含與當前路徑相關的所有信息。
  • 常用屬性:
    • this.$route.path:當前路徑,如 /user/123
    • this.$route.params:動態路由參數,如 { id: 123 }
    • this.$route.query:查詢參數,如 ?tab=profile 對應 { tab: 'profile' }
    • this.$route.name:當前路由的名稱。
    • this.$route.meta:路由元信息,常用於權限控制。

簡言之:router 是“路由器”,負責操作;route 是“當前路線”,負責提供信息。

三、導航守衞的種類

Vue Router 提供了多種導航守衞,用於在路由跳轉前後執行邏輯控制,分為三大類:

1. 全局守衞

作用於整個應用,定義在 router 實例上:

  • router.beforeEach(to, from, next):全局前置守衞,常用於登錄驗證。
  • router.beforeResolve(to, from, next):全局解析守衞,2.5+ 引入,所有組件內守衞和異步路由組件解析完成後觸發。
  • router.afterEach(to, from):全局後置鈎子,不能攔截導航,常用於頁面埋點。

2. 路由獨享守衞

定義在單個路由配置中,僅對該路由生效:

  • beforeEnter(to, from, next):進入該路由前觸發,用法與全局守衞類似。

3. 組件內守衞

定義在 Vue 組件內部,與組件生命週期緊密結合:

  • beforeRouteEnter(to, from, next):組件被激活前調用,此時組件實例尚未創建,無法訪問 this
  • beforeRouteUpdate(to, from, next):當前路由改變但組件被複用時調用(如 /user/1/user/2)。
  • beforeRouteLeave(to, from, next):離開當前路由時調用,可用於提示用户保存未提交的表單。

四、完整的導航解析流程

Vue Router 的導航過程是一個鏈式調用的過程,每一步都可以中斷或繼續。以下是完整的流程:

  1. 導航觸發:用户點擊 <router-link> 或調用 $router.push()
  2. 調用失活組件的 beforeRouteLeave:如從 /user/1 跳轉到 /about
  3. 調用全局 beforeEach 守衞。
  4. 調用重用組件的 beforeRouteUpdate(若組件被複用)。
  5. 調用路由獨享的 beforeEnter
  6. 解析異步組件(若該路由配置了異步組件)。
  7. 調用激活組件的 beforeRouteEnter
  8. 調用全局 beforeResolve 守衞。
  9. 導航被確認。
  10. 調用全局 afterEach 鈎子。
  11. 觸發 DOM 更新。
  12. 執行 beforeRouteEnternext 的回調,此時組件實例已創建,可通過回調參數訪問。