引言
Vue Router 是 Vue.js 的官方路由库,为单页应用(SPA)提供完整的导航和路由管理功能。从 Vue 3 开始,Vue Router 4 带来了 Composition API 支持、更好的 TypeScript 支持以及更灵活的 API 设计。本文将深入讲解 Vue Router 的核心概念和实战技巧。
一、基础配置与安装
1.1 安装
css
npm install vue-router@4
1.2 创建路由实例
javascript
// router/index.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes: RouteRecordRaw[] = [
{
path: '/',
name: 'Home',
component: Home,
meta: { title: '首页' }
},
{
path: '/about',
name: 'About',
component: About,
meta: { title: '关于我们' }
},
{
path: '/user/:id',
name: 'User',
component: () => import('../views/User.vue'),
meta: { title: '用户详情' }
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
1.3 在应用中使用
javascript
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
二、核心功能实战
2.1 编程式导航
xml
<!-- 组件内导航 -->
<template>
<div>
<!-- 声明式导航 -->
<router-link to="/about">关于我们</router-link>
<!-- 编程式导航 -->
<button @click="goHome">返回首页</button>
<button @click="goUser(123)">查看用户</button>
<button @click="goBack">返回</button>
</div>
</template>
<script setup lang="ts">
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const goHome = () => {
router.push('/')
}
const goUser = (id: number) => {
router.push({
name: 'User',
params: { id }
})
// 或者
// router.push(`/user/${id}`)
}
const goBack = () => {
router.back()
}
// 获取当前路由信息
console.log(route.path) // 当前路径
console.log(route.params) // 路由参数
console.log(route.query) // 查询参数
</script>
2.2 动态路由与参数
arduino
// 带参数的路由
{
path: '/user/:id',
component: User,
props: true // 将 params 作为 props 传递
}
// 在组件中使用
<script setup lang="ts">
import { useRoute } from 'vue-router'
const route = useRoute()
const userId = route.params.id
// 带可选参数
{
path: '/user/:id?',
component: User
}
// 带正则验证的参数
{
path: '/user/:id(\d+)',
component: User
}
2.3 查询参数
php
// 添加查询参数
router.push({
path: '/search',
query: { q: 'vue', page: 1 }
})
// 在组件中获取
const searchQuery = route.query.q
const page = route.query.page
三、高级特性
3.1 路由守卫
javascript
// 全局前置守卫
router.beforeEach((to, from, next) => {
const isAuthenticated = localStorage.getItem('token')
if (to.meta.requiresAuth && !isAuthenticated) {
next({ name: 'Login', query: { redirect: to.fullPath } })
} else {
next()
}
})
// 全局后置守卫
router.afterEach((to, from) => {
document.title = to.meta.title || '我的应用'
})
// 路由独享守卫
const routes = [
{
path: '/admin',
component: Admin,
beforeEnter: (to, from, next) => {
if (isAdmin()) {
next()
} else {
next('/403')
}
}
}
]
// 组件内守卫
<script setup lang="ts">
import { onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router'
// 路由更新时调用(参数变化)
onBeforeRouteUpdate((to, from) => {
// 重新获取数据
fetchData(to.params.id)
})
// 路由离开前调用
onBeforeRouteLeave((to, from) => {
if (hasUnsavedChanges()) {
const confirmed = window.confirm('确定要离开吗?未保存的内容将丢失')
if (!confirmed) {
return false
}
}
})
</script>
3.2 懒加载
javascript
// 路由懒加载
const routes = [
{
path: '/dashboard',
name: 'Dashboard',
component: () => import('../views/Dashboard.vue'),
meta: { title: '仪表盘' }
},
{
path: '/settings',
name: 'Settings',
component: () => import('../views/Settings.vue'),
meta: { title: '设置' }
}
]
// 带预加载提示
const routes = [
{
path: '/heavy-page',
component: () => import({
webpackPrefetch: true,
webpackChunkName: 'heavy-page'
}, '../views/HeavyPage.vue')
}
]
3.3 嵌套路由
javascript
const routes = [
{
path: '/user',
component: UserLayout,
children: [
{
path: '',
redirect: 'profile'
},
{
path: 'profile',
component: UserProfile,
name: 'UserProfile'
},
{
path: 'settings',
component: UserSettings,
name: 'UserSettings'
}
]
}
]
// 在父组件中使用
<template>
<div>
<h1>用户中心</h1>
<nav>
<router-link to="/user/profile">个人资料</router-link>
<router-link to="/user/settings">设置</router-link>
</nav>
<router-view />
</div>
</template>
3.4 命名视图
ini
const routes = [
{
path: '/dashboard',
components: {
default: DashboardMain,
sidebar: DashboardSidebar,
footer: DashboardFooter
}
}
]
// 模板中使用
<template>
<router-view />
<router-view name="sidebar" />
<router-view name="footer" />
</template>
四、实战技巧
4.1 路由元信息
vbnet
const routes = [
{
path: '/admin',
component: Admin,
meta: {
requiresAuth: true,
requiresAdmin: true,
title: '管理后台',
roles: ['admin', 'superadmin']
}
}
]
// 在守卫中检查
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login')
return
}
if (to.meta.requiresAdmin && !isAdmin()) {
next('/403')
return
}
next()
})
4.2 滚动行为
typescript
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
// 回到顶部
if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
})
// 平滑滚动到指定元素
const scrollToElement = (id: string) => {
const element = document.getElementById(id)
if (element) {
element.scrollIntoView({ behavior: 'smooth' })
}
}
4.3 路由缓存
xml
<!-- 使用 keep-alive 缓存路由组件 -->
<template>
<router-view v-slot="{ Component, route }">
<keep-alive>
<component :is="Component" :key="route.name" v-if="$route.meta.keepAlive" />
</keep-alive>
<component :is="Component" v-if="!$route.meta.keepAlive" />
</router-view>
</template>
<script setup lang="ts">
// 组件生命周期钩子
import { onActivated, onDeactivated } from 'vue'
onActivated(() => {
// 组件被激活时调用
console.log('组件已激活')
})
onDeactivated(() => {
// 组件被缓存时调用
console.log('组件已缓存')
})
</script>
五、常见问题与解决方案
5.1 404 处理
arduino
const routes = [
// ... 其他路由
{
path: '/:pathMatch(.*)*',
name: 'NotFound',
component: NotFound,
meta: { title: '页面不存在' }
}
]
5.2 路由重复跳转警告
go
// 添加自定义错误处理
const router = createRouter({
history: createWebHistory(),
routes
})
// 覆盖默认错误处理
router.onError((error) => {
if (
error.message.includes('Avoided redundant navigation') ||
error.message.includes('Navigation cancelled')
) {
// 忽略重复导航错误
return
}
console.error(error)
})
总结
Vue Router 提供了强大的路由管理能力,从基础的页面导航到复杂的路由守卫、懒加载和嵌套路由。掌握这些核心功能,可以构建出结构清晰、性能优秀的单页应用。
关键要点:
- 使用路由懒加载优化首屏加载性能
- 利用路由元信息进行权限控制
- 合理使用路由守卫保护敏感页面
- 注意处理路由参数和查询字符串
- 使用命名视图和嵌套路由组织复杂布局
通过实践这些技巧,你的 Vue 应用将拥有更好的用户体验和可维护性。