前置知识: Vue 3

Vue Router 详解

00:00
3 min Intermediate 2026/5/3

路由配置、导航守卫、懒加载与路由元信息。

1. Vue Router 概述

Vue Router 是 Vue.js 官方的路由管理器,它与 Vue.js 核心深度集成,让构建单页应用变得更加简单。

1.1 主要特性

  • 嵌套路由:支持复杂的路由结构
  • 动态路由:支持参数化路由
  • 路由守卫:提供导航守卫机制
  • 编程式导航:通过 API 进行导航
  • 命名路由:使用命名路由简化路由跳转
  • 路由元信息:为路由添加自定义数据
  • 滚动行为:控制导航时的滚动位置

2. 环境搭建

2.1 安装 Vue Router

 # 使用 npm
 npm install vue-router@4
 # 使用 yarn
 yarn add vue-router@4

2.2 基本配置

 // router/index.ts
 import { createRouter, createWebHistory } from 'vue-router'
 import Home from '../views/Home.vue'
 const routes = [
  {
  path: '/',
  name: 'Home',
  component: Home
  },
  {
  path: '/about',
  name: 'About',
  component: () => import('../views/About.vue')
  }
 ]
 const router = createRouter({
  history: createWebHistory(),
  routes
 }
 export default router

2.3 注册路由

// main.ts
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
const app = createApp(App);
app.use(router);
app.mount('#app');

3. 基础用法

3.1 路由链接

<template>
  <nav>
    <router-link to="/">首页</router-link>
    <router-link to="/about">关于</router-link>
  </nav>
  <router-view></router-view>
</template>

3.2 动态路由

// 路由配置
const routes = [
  {
    path: '/user/:id',
    name: 'User',
    component: () => import('../views/User.vue'),
  },
];
<!-- User.vue -->
<template>
  <div>
    <h1>用户详情</h1>
    <p>用户 ID: {{ $route.params.id }}</p>
  </div>
</template>

3.3 嵌套路由

// 路由配置
const routes = [
  {
    path: '/user',
    component: () => import('../views/UserLayout.vue'),
    children: [
      {
        path: '',
        name: 'UserList',
        component: () => import('../views/UserList.vue'),
      },
      {
        path: ':id',
        name: 'UserDetail',
        component: () => import('../views/UserDetail.vue'),
      },
    ],
  },
];

4. 路由守卫

4.1 全局守卫

// 全局前置守卫
router.beforeEach((to, from, next) => {
  // 检查用户是否登录
  const isLoggedIn = localStorage.getItem('token');
  if (to.meta.requiresAuth && !isLoggedIn) {
    next('/login');
  } else {
    next();
  }
});
// 全局后置守卫
router.afterEach((to, from) => {
  // 可以在这里添加页面标题更新等操作
  document.title = to.meta.title || '默认标题';
});

4.2 路由独享守卫

const routes = [
  {
    path: '/admin',
    component: () => import('../views/Admin.vue'),
    beforeEnter: (to, from, next) => {
      // 检查用户是否为管理员
      const isAdmin = localStorage.getItem('role') === 'admin';
      if (isAdmin) {
        next();
      } else {
        next('/');
      }
    },
  },
];

4.3 组件内守卫

<script setup lang="ts">
import { onBeforeRouteEnter, onBeforeRouteUpdate, onBeforeRouteLeave } from 'vue-router';
// 进入路由前
onBeforeRouteEnter((to, from, next) => {
  console.log('进入路由前');
  next();
});
// 路由更新时
onBeforeRouteUpdate((to, from, next) => {
  console.log('路由更新时');
  next();
});
// 离开路由前
onBeforeRouteLeave((to, from, next) => {
  if (confirm('确定要离开吗?')) {
    next();
  } else {
    next(false);
  }
});
</script>

5. 编程式导航

5.1 基本导航

<script setup lang="ts">
import { useRouter } from 'vue-router';
const router = useRouter();
function navigateToAbout() {
  router.push('/about');
}
function navigateToUser(id: number) {
  router.push({
    name: 'User',
    params: { id },
  });
}
function goBack() {
  router.back();
}
function goForward() {
  router.forward();
}
function navigateReplace() {
  router.replace('/about');
}
</script>

5.2 导航守卫中的编程式导航

router.beforeEach((to, from, next) => {
  if (to.path === '/login' && isLoggedIn) {
    next('/');
  } else {
    next();
  }
});

6. 路由元信息

6.1 定义路由元信息

const routes = [
  {
    path: '/admin',
    component: () => import('../views/Admin.vue'),
    meta: {
      requiresAuth: true,
      role: 'admin',
      title: '管理员页面',
    },
  },
];

6.2 使用路由元信息

router.beforeEach((to, from, next) => {
  // 检查是否需要认证
  if (to.meta.requiresAuth) {
    // 检查用户是否登录
    const isLoggedIn = localStorage.getItem('token');
    if (!isLoggedIn) {
      next('/login');
      return;
    }
    // 检查用户角色
    if (to.meta.role) {
      const userRole = localStorage.getItem('role');
      if (userRole !== to.meta.role) {
        next('/');
        return;
      }
    }
  }
  // 更新页面标题
  document.title = to.meta.title || '默认标题';
  next();
});

7. 滚动行为

7.1 基本配置

 const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
  // 如果有保存的位置,返回该位置
  if (savedPosition) {
  return savedPosition
  } else {
  // 否则滚动到顶部
  return { top: 0 }
  }
  }
 }

7.2 自定义滚动行为

 const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior(to, from, savedPosition) {
  if (savedPosition) {
  return savedPosition
  } else if (to.hash) {
  // 如果有哈希值,滚动到对应元素
  return {
  el: to.hash,
  behavior: 'smooth'
  }
  } else {
  return { top: 0 }
  }
  }
 }

8. 路由懒加载

8.1 基本用法

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import('../views/Home.vue'),
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue'),
  },
];

8.2 命名 chunk

const routes = [
  {
    path: '/',
    name: 'Home',
    component: () => import(/* webpackChunkName: "home" */ '../views/Home.vue'),
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue'),
  },
];

9. 路由模块化

9.1 模块化路由配置

// router/modules/user.ts
import { RouteRecordRaw } from 'vue-router';
const userRoutes: RouteRecordRaw[] = [
  {
    path: '/user',
    component: () => import('../../views/user/UserLayout.vue'),
    children: [
      {
        path: '',
        name: 'UserList',
        component: () => import('../../views/user/UserList.vue'),
      },
      {
        path: ':id',
        name: 'UserDetail',
        component: () => import('../../views/user/UserDetail.vue'),
      },
    ],
  },
];
export default userRoutes;
 // router/index.ts
 import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
 import userRoutes from './modules/user'
 const routes: RouteRecordRaw[] = [
  {
  path: '/',
  name: 'Home',
  component: () => import('../views/Home.vue')
  },
  ...userRoutes
 ]
 const router = createRouter({
  history: createWebHistory(),
  routes
 }
 export default router

10. 常见问题与解决方案

10.1 路由参数变化时组件不更新

问题:当路由参数变化时,组件不会重新渲染 解决方案

<script setup lang="ts">
import { watch, useRoute } from 'vue-router';
const route = useRoute();
// 监听路由参数变化
watch(
  () => route.params.id,
  (newId) => {
    // 处理参数变化
    fetchData(newId);
  }
);
</script>

10.2 嵌套路由的默认子路由

问题嵌套路由需要一个默认的路由 解决方案

const routes = [
  {
    path: '/user',
    component: () => import('../views/UserLayout.vue'),
    children: [
      {
        path: '', // 空路径作为默认子路由
        name: 'UserList',
        component: () => import('../views/UserList.vue'),
      },
    ],
  },
];

10.3 路由守卫中的无限循环

问题:在路由守卫中使用 next('/login') 导致无限循环 解决方案

router.beforeEach((to, from, next) => {
  const isLoggedIn = localStorage.getItem('token');
  if (to.path === '/login') {
    // 如果已经在登录页面,直接放行
    next();
  } else if (to.meta.requiresAuth && !isLoggedIn) {
    // 如果需要认证但未登录,跳转到登录页面
    next('/login');
  } else {
    // 其他情况放行
    next();
  }
});

11. 最佳实践

  1. 使用命名路由:提代码可读性和可维护
  2. 使用路由元信息:集中管理路由相关配置
  3. 使用路由懒加载减少初始加载时间
  4. 使用模块化路由:提代码组织
  5. 合理使用路由守卫实现权限控制导航逻辑
  6. 使用 TypeScript提供类型安全
  7. 测试路由:确保路由配置正确

12. 总结

Vue Router 是 Vue3 生态系统中不可或缺的一部分,它提供了强大的路由管理功能,使构建应用变得更加简单效。通过本教程的学习,你应该已经掌握了 Vue Router概念和使用方法,可以在实际项目中灵活运用。

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式