在单页面应用(SPA)开发中,路由管理是至关重要的一环。Vue Router 作为 Vue.js 官方的路由管理器,为我们提供了强大的路由功能。
一、什么是 Vue Router?
Vue Router 是 Vue.js 的官方路由管理器,它与 Vue.js 核心深度集成,让用 Vue.js 构建单页面应用变得轻而易举。
核心功能:
- 嵌套路由映射
- 模块化的路由配置
- 路由参数、查询、通配符
- 强大的导航守卫
- 自动的 CSS 类链接激活
- HTML5 history 模式或 hash 模式
二、安装与基础配置
1. 安装
bash
npm install vue-router@4
2. 基础路由配置
此处为路由配置请求的路径,Home、About是我们创建好的页面组件,需要在这里引用。在routes数组中配置请求响应:如果请求路径为'/',我们应用Home组件,请求路径为'/about',应用About组件。
javascript
// router/index.js(或ts)
import { 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
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router
3. 在 main.js(或ts) 中挂载
javascript
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
//注册路由
app.use(router)
app.mount('#app')
三、路由视图和导航
完成以上前置配置处理后,我们根据需要在挂载完成后的文件内进行组件跳转逻辑书写。
1. 根组件配置
router-link元素类似于增强版本的a元素,向router发送导航请求,to的内容即为请求路径 ,再由router根据收到的路径匹配路由配置,找到对应组件,并在router-view上渲染。(router-view稍后提到)
- 它阻止了默认的页面跳转行为
- 使用 Vue Router 的 API 进行客户端导航
- 自动添加激活状态的 CSS 类
javascript
<!-- App.vue 向router发送请求的导航界面-->
<template>
<div id="app">
<nav class="navigation">
<router-link to="/" class="nav-link">首页</router-link>
<router-link to="/about" class="nav-link">关于我们</router-link>
<router-link :to="{ name: 'User', params: { id: 123 }}" class="nav-link">
用户页面
</router-link>
</nav>
<!-- 路由出口 router分配的组件渲染到这里-->
<main class="main-content">
<router-view />
</main>
</div>
</template>
<style scoped>
.navigation {
padding: 1rem;
background-color: #f5f5f5;
border-bottom: 1px solid #ddd;
}
.nav-link {
margin-right: 1rem;
text-decoration: none;
color: #333;
}
.nav-link.router-link-active {
color: #42b883;
font-weight: bold;
}
</style>
以上步骤完成后,点击首页链接,router会自动为页面分配引入的Home组件,同时,点击关于我们链接,router也会自动分配About组件。
2. 编程式导航
在实际项目中,我们经常需要在 JavaScript 中进行页面跳转:
javascript
<template>
<div class="user-actions">
<button @click="viewProfile" class="btn btn-primary">查看资料</button>
<button @click="goBack" class="btn btn-secondary">返回</button>
<button @click="goToSettings" class="btn btn-outline">设置</button>
</div>
</template>
<script setup>
import { useRouter, useRoute } from 'vue-router'
const router = useRouter()
const route = useRoute()
const viewProfile = () => {
// 多种导航方式
router.push('/profile')
// 或使用命名路由
// router.push({ name: 'Profile' })
// 或带查询参数
// router.push({ path: '/profile', query: { tab: 'info' }})
}
const goBack = () => {
// 返回上一页
router.go(-1)
}
const goToSettings = () => {
// 替换当前路由,不会留下历史记录
router.replace({ name: 'Settings' })
}
</script>
四、动态路由和参数传递
在需要接收的动态数据前加上:,如:'/user/:id'
1. 动态路由配置
javascript
// router/index.js
const routes = [
{
path: '/user/:id',
name: 'User',
component: () => import('../views/User.vue'),
props: true // 将路由参数作为 props 传递
},
{
path: '/category/:category/posts',
name: 'CategoryPosts',
component: () => import('../views/CategoryPosts.vue')
},
{
path: '/search',
name: 'Search',
component: () => import('../views/Search.vue')
}
]
2. 在组件中处理参数
javascript
<!-- User.vue -->
<template>
<div class="user-detail">
<div class="user-header">
<h1>用户详情</h1>
<p class="user-id">用户ID: {{ userId }}</p>
</div>
<div class="user-content">
<div v-if="loading" class="loading">加载中...</div>
<div v-else-if="user" class="user-info">
<img :src="user.avatar" :alt="user.name" class="avatar">
<h2>{{ user.name }}</h2>
<p>{{ user.bio }}</p>
</div>
<div v-else class="error">用户不存在</div>
</div>
</div>
</template>
<script setup>
import { ref, watch, onMounted } from 'vue'
import { useRoute } from 'vue-router'
// 使用 useRoute 获取当前路由信息
const route = useRoute()
// 响应式数据
const userId = ref(route.params.id)
const user = ref(null)
const loading = ref(false)
// 获取用户数据的函数
async function fetchUserData(id) {
loading.value = true
try {
// 模拟 API 调用
const response = await fetch(`/api/users/${id}`)
user.value = await response.json()
} catch (error) {
console.error('获取用户数据失败:', error)
user.value = null
} finally {
loading.value = false
}
}
// 组件挂载时获取数据
onMounted(() => {
fetchUserData(userId.value)
})
// 监听路由参数变化
watch(
() => route.params.id,
(newId) => {
userId.value = newId
fetchUserData(newId)
}
)
</script>
<style scoped>
.user-detail {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
}
.avatar {
width: 100px;
height: 100px;
border-radius: 50%;
}
.loading {
text-align: center;
padding: 2rem;
}
</style>
五、实用技巧
1. 路由懒加载
javascript
// 使用动态 import 实现懒加载
const routes = [
{
path: '/heavy-component',
component: () => import(/* webpackChunkName: "heavy" */ '../views/HeavyComponent.vue')
}
]
2. 滚动行为控制
javascript
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
// 返回顶部
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth'
}
}
// 保持滚动位置
if (savedPosition) {
return savedPosition
}
// 默认滚动到顶部
return { top: 0 }
}
})
3. 错误处理
javascript
// 添加全局错误处理
router.onError((error) => {
console.error('路由错误:', error)
// 处理 chunk 加载失败
if (/loading chunk \d+ failed/.test(error.message)) {
window.location.reload()
}
})
总结
Vue Router 4 提供了强大而灵活的路由管理方案,与 Vue 3 的 Composition API 完美结合,让路由管理变得更加直观和强大。希望这篇指南能帮助你在实际项目中更好地使用 Vue Router!
进一步学习: