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 提供了强大的路由管理功能,合理使用懒加载、路由守卫和嵌套路由,可以构建出高性能、可维护的前端应用。