一、Vue Router 簡介
Vue Router 是 Vue.js 官方的路由管理器,它與 Vue.js 核心深度集成,用于構建單頁面應用(SPA)。單頁面應用是指整個應用只有一個 HTML 頁面,通過動態切換頁面內容來模擬多頁面跳轉的效果,從而提升用戶體驗和頁面加載效率。
Vue Router 的核心功能包括:
- 嵌套路由映射:支持根據組件結構嵌套路由配置。
- 路由參數:可以在路由路徑中傳遞參數,實現動態路由。
- 路由守衛:提供了導航守衛功能,用于控制路由的訪問權限等。
- 編程式導航:通過 JavaScript 代碼實現路由跳轉。
- 命名路由和命名視圖:便于更靈活地配置和使用路由。
二、Vue Router 的安裝與配置
2.1 安裝 Vue Router
在 Vue 3 項目中,通過 npm 或 yarn 安裝 Vue Router(需安裝 4.x 版本,適配 Vue 3):
# 使用 npmnpm install vue-router@4# 使用 yarnyarn add vue-router@4
2.2 基本配置
首先,創建路由配置文件,定義路由規則;然后,在入口文件中創建路由實例并掛載到應用。
步驟 1:創建路由配置文件
// router/index.jsimport { createRouter, createWebHistory } from 'vue-router'// 導入組件import Home from '../views/Home.vue'import About from '../views/About.vue'// 路由規則數組,每個規則對應一個路由const routes = [{path: '/', // 路由路徑name: 'Home', // 路由名稱(可選)component: Home // 路由對應的組件},{path: '/about',name: 'About',component: About// 也可以使用懶加載的方式導入組件(推薦)// component: () => import('../views/About.vue')}]// 創建路由實例const router = createRouter({// 路由模式:createWebHistory 是 HTML5 history 模式(無 # 號)// 另一種是 createWebHashHistory(有 # 號)history: createWebHistory(),routes // 路由規則})export default router
懶加載組件的方式可以減小初始打包體積,提高頁面加載速度,推薦在實際項目中使用。
步驟 2:在入口文件中掛載路由
// main.jsimport { createApp } from 'vue'import App from './App.vue'import router from './router' // 導入路由實例import { createPinia } from 'pinia'const app = createApp(App)const pinia = createPinia()app.use(pinia)app.use(router) // 掛載路由app.mount('#app')
步驟 3:在根組件中添加路由出口
路由出口(<router-view>)是路由對應的組件渲染的位置,需要在根組件(通常是 App.vue)中添加:
<!-- App.vue --><template><div id="app"><!-- 路由導航鏈接 --><nav><router-link to="/">Home</router-link> |<router-link to="/about">About</router-link></nav><!-- 路由出口:匹配的組件將在這里渲染 --><router-view /></div></template><style>/* 可以為激活的路由鏈接添加樣式 */router-link.active {color: red;text-decoration: none;}</style>
<router-link> 用于生成路由導航鏈接,to 屬性指定目標路由路徑。默認會被渲染為 <a> 標簽,當路由匹配時,會自動添加 active 類,便于設置激活樣式。
三、路由跳轉與參數傳遞
3.1 聲明式導航(<router-link>)
通過 <router-link> 標簽實現路由跳轉,適用于模板中的靜態導航。
基本用法
<template><div><!-- 直接指定路徑 --><router-link to="/">首頁</router-link><!-- 使用路由名稱(配合 params 傳遞參數時必須使用名稱) --><router-link :to="{ name: 'About' }">關于我們</router-link></div></template>
傳遞參數
可以通過路由路徑的動態片段(params)或查詢字符串(query)傳遞參數。
params 參數(動態路由)
首先,在路由規則中定義動態片段(以 : 開頭):
// router/index.jsconst routes = [{path: '/user/:id', // :id 是動態參數name: 'User',component: () => import('../views/User.vue')}]
然后,在導航時傳遞參數:
<template><div><!-- 直接在路徑中傳遞參數 --><router-link to="/user/123">用戶 123</router-link><!-- 使用路由名稱和 params 傳遞參數 --><router-link :to="{ name: 'User', params: { id: 456 } }">用戶 456</router-link></div></template>
在目標組件中獲取 params 參數:
<!-- views/User.vue --><template><div><h1>用戶頁面</h1><p>用戶 ID:{{ $route.params.id }}</p></div></template><script setup>import { useRoute } from 'vue-router'// 在組合式 API 中,通過 useRoute 獲取路由信息const route = useRoute()console.log('用戶 ID:', route.params.id)</script>
query 參數(查詢字符串)
query 參數類似于 URL 中的查詢字符串(如 ?name=張三&age=20),無需在路由規則中定義,直接傳遞即可:
<template><div><router-link :to="{ path: '/search', query: { keyword: 'vue', page: 1 } }">搜索</router-link></div></template>
在目標組件中獲取 query 參數:
<!-- views/Search.vue --><template><div><h1>搜索頁面</h1><p>關鍵詞:{{ $route.query.keyword }}</p><p>頁碼:{{ $route.query.page }}</p></div></template><script setup>import { useRoute } from 'vue-router'const route = useRoute()console.log('搜索關鍵詞:', route.query.keyword)</script>
3.2 編程式導航(router.push)
通過 JavaScript 代碼調用 router.push 方法實現路由跳轉,適用于需要在事件處理或邏輯判斷后進行導航的場景。
在組合式 API 中,通過 useRouter 獲取路由實例:
<template><div><button @click="goToHome">前往首頁</button><button @click="goToUser">前往用戶頁面</button><button @click="goToSearch">前往搜索頁面</button></div></template><script setup>import { useRouter } from 'vue-router'// 獲取路由實例const router = useRouter()// 前往首頁const goToHome = () => {router.push('/')// 或使用路由名稱// router.push({ name: 'Home' })}// 前往用戶頁面(傳遞 params 參數)const goToUser = () => {router.push({ name: 'User', params: { id: 789 } })}// 前往搜索頁面(傳遞 query 參數)const goToSearch = () => {router.push({path: '/search',query: { keyword: 'pinia', page: 2 }})}</script>
router.push 的參數格式與 <router-link> 的 to 屬性一致,可以是字符串路徑,也可以是包含 path、name、params、query 等的對象。
四、嵌套路由
嵌套路由用于實現頁面的層級結構,例如在父頁面中嵌套子頁面。
4.1 配置嵌套路由
在路由規則中,通過 children 屬性定義子路由:
// router/index.jsconst routes = [{path: '/dashboard',name: 'Dashboard',component: () => import('../views/Dashboard.vue'),// 子路由children: [{// 子路由的 path 可以不帶 /,表示相對父路由路徑path: 'profile',name: 'Profile',component: () => import('../views/Profile.vue')},{path: 'settings',name: 'Settings',component: () => import('../views/Settings.vue')}]}]
4.2 在父組件中添加子路由出口
父組件需要包含 <router-view> 作為子路由的出口,子路由對應的組件會渲染到這里:
<!-- views/Dashboard.vue --><template><div><h1>儀表盤</h1><nav><router-link to="/dashboard/profile">個人資料</router-link> |<router-link to="/dashboard/settings">設置</router-link></nav><!-- 子路由出口:子組件會在這里渲染 --><router-view /></div></template>
訪問 /dashboard/profile 時,Profile 組件會渲染到 Dashboard 組件的 <router-view> 中;訪問 /dashboard/settings 時,Settings 組件會渲染到該位置。
五、路由守衛
路由守衛用于在路由導航過程中進行攔截和控制,例如驗證用戶登錄狀態、權限檢查等。Vue Router 提供了全局守衛、路由獨享守衛和組件內守衛。
5.1 全局前置守衛(beforeEach)
全局前置守衛會在每次路由跳轉前觸發,適用于全局的權限控制。
// router/index.jsimport router from './index'router.beforeEach((to, from, next) => {// to:即將要進入的目標路由對象// from:當前正要離開的路由對象// next:函數,決定是否繼續導航console.log('即將從', from.path, '跳轉到', to.path)// 示例:判斷用戶是否登錄,未登錄則跳轉到登錄頁const isLogin = localStorage.getItem('isLogin') === 'true'// 不需要登錄的路由白名單const whiteList = ['/login']if (whiteList.includes(to.path)) {// 白名單路由,直接放行next()} else {if (isLogin) {// 已登錄,放行next()} else {// 未登錄,跳轉到登錄頁next('/login')}}})
next 函數的用法:
- next():繼續導航到目標路由。
- next('/path') 或 next({ path: '/path' }):跳轉到指定路由。
- next(false):中斷當前導航。
5.2 組件內守衛
組件內守衛包括 beforeRouteEnter、beforeRouteUpdate 和 beforeRouteLeave,定義在組件內部。
<!-- views/Profile.vue --><template><div><h1>個人資料</h1></div></template><script setup>import { onBeforeRouteEnter, onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'// 進入組件前觸發(此時組件實例還未創建,不能使用 this 或 setup 中的變量)onBeforeRouteEnter((to, from, next) => {console.log('即將進入個人資料頁面')// 可以通過 next 的回調函數訪問組件實例next(vm => {// vm 是組件實例console.log('組件實例:', vm)})})// 組件更新時觸發(例如路由參數變化但組件復用)onBeforeRouteUpdate((to, from, next) => {console.log('個人資料頁面路由參數發生變化')next()})// 離開組件時觸發onBeforeRouteLeave((to, from, next) => {console.log('即將離開個人資料頁面')// 示例:提示用戶是否保存修改const isSave = confirm('是否保存修改?')if (isSave) {next()} else {// 取消離開next(false)}})</script>
六、總結
Vue Router 是 Vue 3 構建單頁面應用的核心工具,通過本文的學習,我們掌握了其基本概念、安裝配置、路由跳轉與參數傳遞、嵌套路由和路由守衛等核心功能。
在實際開發中,合理規劃路由結構、使用懶加載優化性能、通過路由守衛控制權限,能夠構建出體驗良好的單頁面應用。后續還可以深入學習命名視圖、路由元信息、滾動行為等高級特性,進一步提升路由的使用效率。