第7章 路由管理
第21节 路由高级特性
7.21.1 路由元信息与过渡动画
路由元信息
路由元信息是Vue Router提供的一种机制,允许我们在路由配置中添加自定义数据,用于权限控制、页面标题设置、动画效果等场景。
// router/index.js
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue'),
meta: {
title: '首页',
requiresAuth: false,
layout: 'default',
transition: 'fade'
}
},
{
path: '/admin',
name: 'Admin',
component: () => import('../views/Admin.vue'),
meta: {
title: '后台管理',
requiresAuth: true,
roles: ['admin'],
layout: 'admin',
transition: 'slide'
}
}
]在导航守卫中访问路由元信息:
router.beforeEach((to, from, next) => {
// 设置页面标题
document.title = to.meta.title || '默认标题'
// 权限验证
const isAuthenticated = localStorage.getItem('token')
const userRole = localStorage.getItem('role')
if (to.meta.requiresAuth) {
if (!isAuthenticated) {
next('/login')
} else if (to.meta.roles && !to.meta.roles.includes(userRole)) {
next('/403')
} else {
next()
}
} else {
next()
}
})路由过渡动画
Vue Router与Vue的<transition>组件结合,可以实现页面切换时的过渡动画效果。
基本过渡效果
<!-- App.vue -->
<template>
<div id="app">
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</nav>
<!-- 路由过渡动画 -->
<transition name="fade" mode="out-in">
<router-view />
</transition>
</div>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>基于路由元信息的动态过渡
<!-- App.vue -->
<template>
<div id="app">
<nav>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-link to="/admin">后台</router-link>
</nav>
<!-- 基于路由元信息的动态过渡 -->
<transition
:name="transitionName"
mode="out-in"
>
<router-view />
</transition>
</div>
</template>
<script>
export default {
data() {
return {
transitionName: 'fade'
}
},
watch: {
$route(to, from) {
// 从路由元信息中获取过渡名称
this.transitionName = to.meta.transition || 'fade'
}
}
}
</script>
<style>
/* 淡入淡出效果 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
/* 滑动效果 */
.slide-enter-active,
.slide-leave-active {
transition: all 0.3s ease;
}
.slide-enter-from {
transform: translateX(100%);
}
.slide-leave-to {
transform: translateX(-100%);
}
</style>7.21.2 路由懒加载与代码分割
路由懒加载是一种优化技术,它允许我们将不同路由对应的组件分割成不同的代码块,只有当路由被访问时才会加载对应的组件代码。
基本懒加载实现
// router/index.js
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/admin',
name: 'Admin',
component: () => import('../views/Admin.vue')
}
]命名代码块
我们可以为懒加载的代码块指定名称,以便在打包时更好地识别和管理:
const routes = [
{
path: '/',
name: 'Home',
component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
},
{
path: '/admin',
name: 'Admin',
component: () => import(/* webpackChunkName: "admin" */ '../views/Admin.vue')
}
]组件懒加载
除了路由级别的懒加载,我们还可以在组件内部实现组件级别的懒加载:
// 在组件中懒加载其他组件
const HeavyComponent = defineAsyncComponent(() =>
import(/* webpackChunkName: "heavy" */ './HeavyComponent.vue')
)
export default {
components: {
HeavyComponent
}
}预加载策略
我们可以使用<link rel="prefetch">或Vue Router的预加载功能来优化用户体验:
// 预加载所有路由组件
const routes = [
{
path: '/',
name: 'Home',
component: () => import(/* webpackPrefetch: true */ '../views/Home.vue')
}
]7.21.3 滚动行为控制
Vue Router允许我们自定义路由切换时的滚动行为,控制页面滚动到指定位置。
基本滚动行为配置
// router/index.js
const router = createRouter({
history: createWebHistory(),
routes,
// 滚动行为配置
scrollBehavior(to, from, savedPosition) {
// 如果有保存的位置,恢复到该位置(如浏览器后退/前进)
if (savedPosition) {
return savedPosition
} else {
// 否则滚动到顶部
return { top: 0 }
}
}
})滚动到指定元素
scrollBehavior(to, from, savedPosition) {
// 如果路由中指定了#hash,滚动到对应元素
if (to.hash) {
return {
el: to.hash,
behavior: 'smooth' // 平滑滚动
}
} else if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}基于路由元信息的滚动行为
scrollBehavior(to, from, savedPosition) {
// 从路由元信息中获取滚动位置
if (to.meta.scrollTo) {
return to.meta.scrollTo
} else if (savedPosition) {
return savedPosition
} else {
return { top: 0 }
}
}
// 路由配置中使用
const routes = [
{
path: '/long-page',
name: 'LongPage',
component: () => import('../views/LongPage.vue'),
meta: {
scrollTo: { top: 0, behavior: 'smooth' }
}
}
]7.21.4 路由模式:Hash vs History
Vue Router支持两种路由模式:Hash模式和History模式。
Hash模式
Hash模式是Vue Router的默认模式,它使用URL的哈希值(#)来模拟路由,不需要服务器配置。
const router = createRouter({
history: createWebHashHistory(),
routes
})特点:
- URL中包含#符号,如:
http://example.com/#/home - 不要求服务器配置,兼容性好
- 刷新页面不会404
- SEO不友好
History模式
History模式使用HTML5的History API来实现路由,URL更加美观,没有#符号。
const router = createRouter({
history: createWebHistory(),
routes
})特点:
- URL更加美观,如:
http://example.com/home - SEO友好
- 要求服务器配置,否则刷新页面会404
- 兼容性要求较高(IE10+)
服务器配置
使用History模式时,需要服务器配置来处理所有请求,将它们重定向到index.html。
Nginx配置示例:
server {
listen 80;
server_name example.com;
root /path/to/your/app;
location / {
try_files $uri $uri/ /index.html;
}
}Apache配置示例:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>Node.js (Express)配置示例:
const express = require('express')
const path = require('path')
const app = express()
app.use(express.static(path.join(__dirname, 'dist')))
app.get('*', (req, res) => {
res.sendFile(path.join(__dirname, 'dist', 'index.html'))
})
app.listen(3000, () => {
console.log('Server is running on port 3000')
})最佳实践与注意事项
路由元信息的合理使用:
- 不要在元信息中存储过多数据,只存储与路由相关的配置
- 元信息适合存储权限、标题、布局、过渡效果等配置
路由懒加载的最佳实践:
- 对所有路由组件使用懒加载,提高初始加载速度
- 合理划分代码块,避免过大的单块代码
- 对不常用的路由组件考虑预加载
滚动行为的设计:
- 大多数情况下,滚动到顶部是最佳体验
- 对长列表页面,可以考虑保持滚动位置
- 使用平滑滚动提升用户体验
路由模式的选择:
- 开发环境:推荐使用History模式,URL更美观
- 生产环境:
- 如果服务器支持,优先选择History模式
- 否则使用Hash模式
- 考虑SEO需求,History模式更友好
小结
本节我们学习了Vue Router的高级特性,包括:
- 路由元信息的定义和使用
- 基于路由的过渡动画
- 路由懒加载与代码分割
- 滚动行为控制
- Hash模式与History模式的对比
这些高级特性可以帮助我们构建更加优化、用户体验更好的单页应用。合理使用这些特性,可以提高应用的性能、SEO友好性和用户体验。
思考与练习
- 实现一个基于路由元信息的权限管理系统,不同角色可以访问不同的路由。
- 为不同路由配置不同的过渡动画效果。
- 使用路由懒加载优化应用性能,并查看打包后的代码分割情况。
- 配置滚动行为,实现页面切换时的平滑滚动效果。
- 对比Hash模式和History模式,尝试在本地服务器上配置History模式。