深入理解 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 不夠美觀,帶有
#符號。
- URL 不夠美觀,帶有
2. history 模式
history 模式依賴 HTML5 提供的 pushState 和 replaceState API,可以在不刷新頁面的情況下修改 URL。
- 監聽機制:通過監聽
popstate事件,捕獲瀏覽器前進/後退操作。 - 優點:
- URL 更乾淨,沒有
#。
- URL 更乾淨,沒有
- 缺點:
- 需要後端配合,刷新頁面或直接訪問子路徑時,需將所有請求重定向到入口文件(如
index.html),否則會返回 404。 - 對低版本瀏覽器支持不佳。
- 需要後端配合,刷新頁面或直接訪問子路徑時,需將所有請求重定向到入口文件(如
二、router 與 route 的區別
在 Vue 組件中,我們常常使用 this.$router 和 this.$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 的導航過程是一個鏈式調用的過程,每一步都可以中斷或繼續。以下是完整的流程:
- 導航觸發:用户點擊
<router-link>或調用$router.push()。 - 調用失活組件的
beforeRouteLeave:如從/user/1跳轉到/about。 - 調用全局
beforeEach守衞。 - 調用重用組件的
beforeRouteUpdate(若組件被複用)。 - 調用路由獨享的
beforeEnter。 - 解析異步組件(若該路由配置了異步組件)。
- 調用激活組件的
beforeRouteEnter。 - 調用全局
beforeResolve守衞。 - 導航被確認。
- 調用全局
afterEach鈎子。 - 觸發 DOM 更新。
- 執行
beforeRouteEnter中next的回調,此時組件實例已創建,可通過回調參數訪問。