Vue Router 最佳实践
基础路由配置
Vue Router 4 是 Vue 3 的官方路由管理器,支持组合式 API。
基本安装与配置
import { createRouter, createWebHistory } from 'vue-router';
import HomeView from '@/views/HomeView.vue';
const routes = [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/about',
name: 'about',
// 懒加载路由
component: () => import('@/views/AboutView.vue'),
},
];
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes,
});
export default router;
路由懒加载
使用动态 import 实现路由懒加载,提升首屏加载速度:
const routes = [
{
path: '/user/:id',
name: 'user',
// 懒加载
component: () => import('@/views/UserView.vue'),
// 路由级代码分割
meta: { requiresAuth: true },
},
];
预加载策略
// vite.config.ts
export default defineConfig({
plugins: [
vue({
script: {
defineModel: true,
},
}),
],
build: {
rollupOptions: {
output: {
manualChunks: {
'vue-vendor': ['vue', 'vue-router', 'pinia'],
},
},
},
},
});
路由守卫
全局前置守卫
router.beforeEach((to, from, next) => {
const isAuthenticated = checkAuth();
if (to.meta.requiresAuth && !isAuthenticated) {
next({ name: 'login', query: { redirect: to.fullPath } });
} else {
next();
}
});
组件内守卫
<script setup lang="ts">
import { onBeforeRouteLeave, onBeforeRouteUpdate } from 'vue-router';
// 路由离开前
onBeforeRouteLeave((to, from) => {
if (hasUnsavedChanges.value) {
return confirm('有未保存的更改,确定要离开吗?');
}
});
// 路由更新时(同一组件不同参数)
onBeforeRouteUpdate((to, from) => {
fetchData(to.params.id);
});
</script>
动态路由
路由参数
const routes = [
{
path: '/user/:id',
name: 'user',
component: UserView,
},
];
// 在组件中使用
<script setup lang="ts">
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
// 获取参数
const userId = route.params.id;
// 编程式导航
router.push({ name: 'user', params: { id: 123 } });
</script>
查询参数
// URL: /search?keyword=vue&page=1
const route = useRoute();
// 获取查询参数
const keyword = route.query.keyword as string;
const page = Number(route.query.page) || 1;
// 导航时传递查询参数
router.push({
path: '/search',
query: { keyword: 'vue', page: 1 },
});
嵌套路由
const routes = [
{
path: '/dashboard',
component: DashboardLayout,
children: [
{
path: '',
name: 'dashboard',
component: DashboardHome,
},
{
path: 'settings',
name: 'settings',
component: SettingsView,
},
{
path: 'profile',
name: 'profile',
component: ProfileView,
},
],
},
];
模板中使用 <router-view>:
<template>
<div class="dashboard">
<aside>
<nav>
<RouterLink to="/dashboard">首页</RouterLink>
<RouterLink to="/dashboard/settings">设置</RouterLink>
<RouterLink to="/dashboard/profile">个人资料</RouterLink>
</nav>
</aside>
<main>
<RouterView />
</main>
</div>
</template>
命名视图
const routes = [
{
path: '/profile',
components: {
default: ProfileView,
sidebar: ProfileSidebar,
},
},
];
<template>
<div class="profile">
<RouterView />
<RouterView name="sidebar" />
</div>
</template>
导航守卫最佳实践
权限控制
// router/index.ts
router.beforeEach(async (to, from) => {
const userStore = useUserStore();
// 未登录时获取用户信息
if (!userStore.isLoggedIn) {
try {
await userStore.fetchUser();
} catch {
return { name: 'login' };
}
}
// 检查路由权限
if (to.meta.permissions) {
const hasPermission = to.meta.permissions.some((p) =>
userStore.permissions.includes(p)
);
if (!hasPermission) {
return { name: 'forbidden' };
}
}
});
路由元信息类型安全
// types/router.ts
declare module 'vue-router' {
interface RouteMeta {
requiresAuth?: boolean;
permissions?: string[];
title?: string;
keepAlive?: boolean;
}
}
常见问题
1. 路由切换时页面未重置
// 使用 key 强制重新渲染
<RouterView :key="route.fullPath" />
2. history 模式 404 问题
服务器配置:
# nginx
location / {
try_files $uri $uri/ /index.html;
}
3. 路由参数变化不触发组件更新
// 使用 watch 监听路由变化
watch(
() => route.params.id,
(newId) => {
fetchData(newId);
},
{ immediate: true }
);
总结
Vue Router 4 提供了强大的路由管理功能,合理使用懒加载、路由守卫和嵌套路由,可以构建出高性能、可维护的前端应用。