核心功能详解
1. 路由守卫(Navigation Guards)
路由守卫是 Vue Router 最强大的功能之一,允许你在路由导航过程中进行控制。
类型和用法:
javascript
// 全局前置守卫
router.beforeEach((to, from, next) => {
// 在导航前执行逻辑
next(); // 必须调用next()来继续导航
});
// 全局解析守卫
router.beforeResolve((to, from, next) => {
// 在导航被确认之前调用
next();
});
// 全局后置钩子
router.afterEach((to, from) => {
// 导航完成后执行
});
// 路由独享守卫
const routes = [
{
path: '/admin',
component: AdminPage,
beforeEnter: (to, from, next) => {
// 特定路由的守卫
next();
}
}
];
// 组件内守卫
const UserProfile = {
beforeRouteEnter(to, from, next) {
// 组件创建前调用
next(vm => {
// 通过vm访问组件实例
});
},
beforeRouteUpdate(to, from, next) {
// 当前路由改变但组件被复用时
this.fetchData(to.params.id);
next();
},
beforeRouteLeave(to, from, next) {
// 离开该组件时调用
next();
}
}
2. 动态路由匹配
动态路由允许根据URL参数动态匹配组件。
javascript
const routes = [
// 基本动态路由
{ path: '/user/:id', component: User },
// 多段参数
{ path: '/user/:id/post/:postId', component: Post },
// 可选参数
{ path: '/user/:id?', component: UserList },
// 正则匹配
{ path: '/:category(blog|news|article)/:id', component: Content },
// 通配符路由
{ path: '/:pathMatch(.*)*', name: 'NotFound', component: NotFound }
];
3. 路由元信息(Meta Fields)
路由元信息允许你在路由上附加自定义数据。
javascript
const routes = [
{
path: '/admin',
component: AdminDashboard,
meta: {
requiresAuth: true,
permissions: ['admin', 'superuser'],
title: '管理控制台'
}
}
];
4. 路由懒加载
使用动态导入实现路由懒加载,优化应用性能。
javascript
const routes = [
{
path: '/dashboard',
component: () => import(/* webpackChunkName: "dashboard" */ '@/views/Dashboard.vue')
},
{
path: '/settings',
component: () => import(/* webpackChunkName: "settings" */ '@/views/Settings.vue')
}
];
5. 嵌套路由
嵌套路由允许创建复杂的UI布局。
javascript
const routes = [
{
path: '/user/:id',
component: UserLayout,
children: [
{
path: '',
component: UserProfile
},
{
path: 'posts',
component: UserPosts
},
{
path: 'settings',
component: UserSettings
}
]
}
];
6. 滚动行为控制
自定义路由切换时的滚动位置。
javascript
const router = createRouter({
history: createWebHistory(),
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition;
} else if (to.hash) {
return {
el: to.hash,
behavior: 'smooth'
};
} else {
return { top: 0, behavior: 'smooth' };
}
}
});
7. 路由过渡效果
使用Vue的Transition组件实现路由切换动画。
vue
<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>
实战案例:电子商务平台路由系统
下面是一个完整的电子商务平台路由实现:
javascript
// router/index.js
import { createRouter, createWebHistory } from 'vue-router';
import { useAuthStore } from '@/stores/auth';
// 路由懒加载
const HomePage = () => import('@/views/HomePage.vue');
const ProductList = () => import('@/views/products/ProductList.vue');
const ProductDetail = () => import('@/views/products/ProductDetail.vue');
const ShoppingCart = () => import('@/views/cart/ShoppingCart.vue');
const CheckoutProcess = () => import('@/views/checkout/CheckoutProcess.vue');
const UserProfile = () => import('@/views/user/UserProfile.vue');
const AdminDashboard = () => import('@/views/admin/Dashboard.vue');
const LoginPage = () => import('@/views/auth/LoginPage.vue');
const NotFound = () => import('@/views/errors/NotFound.vue');
const routes = [
{
path: '/',
name: 'home',
component: HomePage,
meta: { title: '首页' }
},
{
path: '/products',
name: 'products',
component: ProductList,
meta: { title: '产品列表' }
},
{
path: '/products/:id(\\d+)', // 只匹配数字ID
name: 'product-detail',
component: ProductDetail,
props: true,
meta: { title: '产品详情' }
},
{
path: '/cart',
name: 'cart',
component: ShoppingCart,
meta: {
title: '购物车',
requiresAuth: true
}
},
{
path: '/checkout',
name: 'checkout',
component: CheckoutProcess,
meta: {
title: '结算',
requiresAuth: true,
disableLeave: true // 防止意外离开
}
},
{
path: '/profile',
name: 'profile',
component: UserProfile,
meta: {
title: '个人资料',
requiresAuth: true
}
},
{
path: '/admin',
name: 'admin',
component: AdminDashboard,
meta: {
title: '管理面板',
requiresAuth: true,
requiresAdmin: true
}
},
{
path: '/login',
name: 'login',
component: LoginPage,
meta: {
title: '登录',
hideForAuth: true // 已登录用户隐藏
}
},
{
path: '/:pathMatch(.*)*',
name: 'not-found',
component: NotFound,
meta: { title: '页面未找到' }
}
];
const router = createRouter({
history: createWebHistory(),
routes,
scrollBehavior() {
return { top: 0 };
}
});
// 全局前置守卫
router.beforeEach(async (to, from, next) => {
const authStore = useAuthStore();
// 设置页面标题
document.title = to.meta.title ? `${to.meta.title} - 电商平台` : '电商平台';
// 检查是否需要登录
if (to.meta.requiresAuth && !authStore.isAuthenticated) {
next({ name: 'login', query: { redirect: to.fullPath } });
return;
}
// 检查是否已登录但访问登录页面
if (to.meta.hideForAuth && authStore.isAuthenticated) {
next({ name: 'home' });
return;
}
// 检查管理员权限
if (to.meta.requiresAdmin && !authStore.isAdmin) {
next({ name: 'forbidden' }); // 应创建一个403页面
return;
}
// 继续导航
next();
});
// 全局后置钩子
router.afterEach((to) => {
// 页面访问统计
trackPageView(to.fullPath);
});
export default router;
支付页面组件内守卫实现
vue
<!-- CheckoutProcess.vue -->
<script>
export default {
data() {
return {
isProcessing: false,
hasUnsavedChanges: true
};
},
beforeRouteLeave(to, from, next) {
// 支付处理中禁止离开
if (this.isProcessing) {
alert('支付处理中,请稍候...');
next(false);
return;
}
// 未完成支付提示
if (this.hasUnsavedChanges && to.name !== 'payment-success') {
const confirmLeave = confirm(
'您有未完成的支付,确定要离开吗?'
);
next(confirmLeave);
} else {
next();
}
},
methods: {
async processPayment() {
this.isProcessing = true;
try {
await this.$store.dispatch('checkout/processPayment');
this.hasUnsavedChanges = false;
this.$router.push({ name: 'payment-success' });
} catch (error) {
alert(`支付失败: ${error.message}`);
} finally {
this.isProcessing = false;
}
}
}
};
</script>
路由元信息与面包屑导航实现
vue
<!-- Breadcrumb.vue -->
<template>
<nav class="breadcrumb">
<router-link to="/">首页</router-link>
<template v-for="(crumb, index) in crumbs" :key="crumb.path">
<span class="separator">/</span>
<router-link
v-if="index < crumbs.length - 1"
:to="crumb.path"
>
{{ crumb.meta.title }}
</router-link>
<span v-else class="current">
{{ crumb.meta.title }}
</span>
</template>
</nav>
</template>
<script>
import { computed } from 'vue';
import { useRoute } from 'vue-router';
export default {
setup() {
const route = useRoute();
const crumbs = computed(() => {
const matched = route.matched.filter(
record => record.meta && record.meta.title
);
// 添加首页
if (matched.length > 0 && matched[0].path !== '/') {
matched.unshift({ path: '/', meta: { title: '首页' } });
}
return matched;
});
return { crumbs };
}
};
</script>
路由模式与技巧
1. 基于角色的动态路由
javascript
function generateRoutes(userRole) {
const baseRoutes = [
{ path: '/', component: HomePage },
{ path: '/products', component: ProductList }
];
const roleBasedRoutes = [];
if (userRole === 'admin') {
roleBasedRoutes.push(
{ path: '/admin', component: AdminDashboard },
{ path: '/analytics', component: AnalyticsDashboard }
);
}
if (userRole === 'customer') {
roleBasedRoutes.push(
{ path: '/profile', component: UserProfile },
{ path: '/orders', component: UserOrders }
);
}
return [...baseRoutes, ...roleBasedRoutes];
}
// 在登录后动态添加路由
authStore.login().then(user => {
const routes = generateRoutes(user.role);
routes.forEach(route => {
router.addRoute(route);
});
});
2. 路由数据预取
javascript
// 在路由配置中
{
path: '/product/:id',
component: ProductDetail,
props: true,
meta: {
prefetch: async (route) => {
// 预取产品数据
const productId = route.params.id;
await store.dispatch('products/prefetchProduct', productId);
}
}
}
// 在全局前置守卫中
router.beforeEach(async (to, from, next) => {
if (to.meta.prefetch) {
try {
await to.meta.prefetch(to);
} catch (error) {
console.error('Prefetch failed:', error);
}
}
next();
});
3. 路由过渡效果
vue
<template>
<router-view v-slot="{ Component, route }">
<transition :name="route.meta.transition || 'fade'">
<component :is="Component" :key="route.fullPath" />
</transition>
</router-view>
</template>
<style>
/* 淡入淡出效果 */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
/* 滑动效果 */
.slide-left-enter-active,
.slide-left-leave-active,
.slide-right-enter-active,
.slide-right-leave-active {
transition: transform 0.4s ease;
}
.slide-left-enter-from {
transform: translateX(100%);
}
.slide-left-leave-to {
transform: translateX(-100%);
}
.slide-right-enter-from {
transform: translateX(-100%);
}
.slide-right-leave-to {
transform: translateX(100%);
}
</style>
<!-- 在路由配置中使用 -->
{
path: '/products',
component: ProductList,
meta: {
title: '产品列表',
transition: 'slide-right'
}
}
总结
Vue Router 的高级功能为构建复杂单页面应用提供了强大支持:
- 路由守卫:实现导航控制、权限验证和数据预加载
- 动态路由:处理参数化URL和复杂匹配场景
- 路由元信息:附加自定义数据用于权限控制、布局配置等
- 路由懒加载:优化应用性能,减少初始加载时间
- 嵌套路由:创建复杂UI布局和层次结构
- 滚动控制:提供更好的用户体验
- 路由过渡:增强页面切换的视觉效果