04-Vue-Router路由管理
Vue Router 路由管理
1. 安装与基础配置
安装 Vue Router
npm install vue-router@4
创建路由实例
// router/index.js import { createRouter, createWebHistory } from 'vue-router'const routes = [
{
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('@/views/About.vue')
},
{
path: '/user/:id',
name: 'User',
component: () => import('@/views/User.vue')
}
]const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在应用中使用
// 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')
2. 路由视图与链接
router-view
<!-- App.vue --> <template> <div id="app"> <nav> <router-link to="/">首页</router-link> <router-link to="/about">关于</router-link> </nav>
<!-- 路由匹配到的组件渲染在这里 -->
<router-view></router-view>
</div>
</template>
router-link
<template> <!-- 基础用法 --> <router-link to="/about">关于</router-link><!-- 命名路由 -->
<router-link :to="{ name: 'User', params: { id: 123 } }">
用户 123
</router-link><!-- 带查询参数 -->
<router-link :to="{ path: '/search', query: { keyword: 'vue' } }">
搜索 Vue
</router-link>
<!-- 自定义标签 -->
<router-link to="/about" custom v-slot="{ navigate, href, isActive }">
<a :href="href" @click="navigate" :class="{ active: isActive }">
关于
</a>
</router-link>
</template>
3. 动态路由
路由参数
const routes = [
{
path: '/user/:id',
name: 'User',
component: User
},
{
// 多个参数
path: '/post/:year/:month',
name: 'Post',
component: Post
},
{
// 可选参数
path: '/search/:keyword?',
name: 'Search',
component: Search
}
]
<!-- 获取路由参数 --> <script setup> import { useRoute } from 'vue-router'const route = useRoute()
console.log(route.params.id) // /user/123 -> '123'
console.log(route.params.year) // /post/2024/01 -> '2024'
console.log(route.params.keyword) // /search -> undefined
</script>
监听参数变化
<script setup> import { watch } from 'vue' import { useRoute } from 'vue-router'const route = useRoute()
// 监听路由变化
watch(
() => route.params.id,
(newId, oldId) => {
// 执行数据获取等操作
console.log(从 ${oldId} 变为 ${newId})
}
)
</script>
4. 嵌套路由
const routes = [
{
path: '/user/:id',
component: User,
children: [
{
// 用户资料 /user/123/profile
path: 'profile',
component: UserProfile
},
{
// 用户文章 /user/123/posts
path: 'posts',
component: UserPosts
},
{
// 默认子路由 /user/123
path: '',
component: UserHome
}
]
}
]
<!-- User.vue --> <template> <div class="user"> <h1>用户 {{ $route.params.id }}</h1><nav>
<router-link :to="/user/${$route.params.id}">首页</router-link>
<router-link :to="/user/${$route.params.id}/profile">资料</router-link>
<router-link :to="/user/${$route.params.id}/posts">文章</router-link>
</nav>
<!-- 子路由渲染在这里 -->
<router-view></router-view>
</div>
</template>
5. 导航编程式
router.push
<script setup> import { useRouter } from 'vue-router'const router = useRouter()
// 字符串路径
router.push('/about')// 带参数对象
router.push({ path: '/user', query: { id: 123 } })// 命名路由
router.push({ name: 'User', params: { id: 123 } })// 带查询参数
router.push({ path: '/search', query: { keyword: 'vue' } })
// 替换当前历史记录
router.replace('/login')
</script>
router.go / router.back / router.forward
// 前进或后退
router.go(-1) // 后退一页
router.go(1) // 前进一页
router.back() // 等同于 go(-1)
router.forward() // 等同于 go(1)
6. 导航守卫
全局前置守卫
// router/index.js router.beforeEach((to, from, next) => { // to: 即将进入的路由 // from: 当前正要离开的路由// 检查是否已登录
const isAuthenticated = localStorage.getItem('token')if (to.meta.requiresAuth && !isAuthenticated) {
// 未登录,重定向到登录页
next({
path: '/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) => {
// 检查用户权限
const hasPermission = checkPermission()
if (hasPermission) {
next()
} else {
next('/403')
}
},
children: [
{
path: 'settings',
component: Settings,
beforeEnter: (to, from, next) => {
// 子路由也可以有守卫
next()
}
}
]
}
]
组件内守卫
<script setup> import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router'// 离开当前路由前
onBeforeRouteLeave((to, from, next) => {
const answer = window.confirm('确定要离开吗?未保存的更改将丢失')
if (answer) {
next()
} else {
next(false)
}
})
// 路由参数变化时(复用组件)
onBeforeRouteUpdate((to, from, next) => {
// 重新获取数据
fetchData(to.params.id)
next()
})
</script>
7. 路由元信息
const routes = [ { path: '/dashboard', component: Dashboard, meta: { requiresAuth: true, title: '控制台', roles: ['admin', 'editor'] } }, { path: '/settings', component: Settings, meta: { requiresAuth: true, title: '设置', roles: ['admin'] } } ]
// 在守卫中使用
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !isLoggedIn()) {
next('/login')
} else if (to.meta.roles && !to.meta.roles.includes(currentUser.role)) {
next('/403')
} else {
next()
}
})
8. 过渡效果
<template> <router-view v-slot="{ Component }"> <transition name="fade" mode="out-in"> <component :is="Component" /> </transition> </router-view> </template><style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
9. 滚动行为
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior(to, from, savedPosition) {
// 有保存的位置(浏览器前进/后退)
if (savedPosition) {
return savedPosition
}
// 锚点定位
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth'
}
}
// 默认滚动到顶部
return { top: 0, behavior: 'smooth' }
}
})
10. 路由懒加载
const routes = [
{
path: '/',
component: () => import('@/views/Home.vue')
},
{
path: '/about',
// webpackChunkName 用于生成带注释的文件名
component: () => import(
/* webpackChunkName: "about" */
'@/views/About.vue'
)
}
]
11. 完整路由配置示例
// router/index.js import { createRouter, createWebHistory } from 'vue-router'const routes = [
{
path: '/',
name: 'Layout',
component: () => import('@/layouts/DefaultLayout.vue'),
children: [
{
path: '',
name: 'Home',
component: () => import('@/views/Home.vue'),
meta: { title: '首页' }
},
{
path: 'about',
name: 'About',
component: () => import('@/views/About.vue'),
meta: { title: '关于我们' }
},
{
path: 'user/:id',
name: 'User',
component: () => import('@/views/User.vue'),
meta: { title: '用户详情' }
}
]
},
{
path: '/login',
name: 'Login',
component: () => import('@/views/Login.vue'),
meta: { title: '登录', public: true }
},
{
path: '/:pathMatch(.)',
name: 'NotFound',
component: () => import('@/views/NotFound.vue'),
meta: { title: '404' }
}
]const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition
return { top: 0 }
}
})// 全局守卫
router.beforeEach((to, from) => {
const isAuthenticated = !!localStorage.getItem('token')if (to.meta.requiresAuth && !isAuthenticated) {
return { path: '/login', query: { redirect: to.fullPath } }
}
})router.afterEach((to) => {
document.title = to.meta.title ?${to.meta.title} - 我的应用: '我的应用'
})
export default router
小结
Vue Router 是 Vue 官方路由管理器,核心功能包括:
- 基础路由:路径映射与组件渲染
- 动态路由:参数传递与监听
- 嵌套路由:多层级页面结构
- 导航守卫:权限控制与路由拦截
- 编程式导航:代码控制路由跳转
- 过渡效果:路由切换动画
- 懒加载:按需加载路由组件

浙公网安备 33010602011771号