Vue Router 路由管理完全指南:从入门到精通前言

前言

大家好!今天我要和大家聊聊 Vue Router,这个 Vue.js 官方的路由管理器。如果你正在开发 Vue 应用,那么路由管理肯定是绕不开的话题。无论是构建简单的单页应用还是复杂的企业级项目,Vue Router 都能帮你轻松实现页面之间的跳转和状态管理

在这篇文章中,我会从最基础的概念开始,一步步带你深入 Vue Router 的世界,最后还会分享一些实际项目中的应用案例。无论你是 Vue 新手还是有一定经验的开发者,相信都能从这篇文章中有所收获

一、什么是 Vue Router?

1、路由的基本概念

首先,我们得搞清楚什么是 "路由"。简单来说,路由就是一组 key-value 的对应关系 。在前端开发中,这个对应关系通常是路径 -> 组件。当用户访问某个路径时,路由系统就会渲染对应的组件

举个生活中的例子,路由就像是一个酒店的前台。客人报出自己的房间号(路径),前台就会指引客人到对应的房间(组件)

2、SPA 应用的特点

Vue Router 主要用于构建单页 Web 应用(SPA),SPA 有以下几个特点:

**(1)、整个应用只有一个完整的页面:**所有内容都在一个 HTML 文件中展示

**(2)、页面不会刷新:**点击导航链接时,页面不会重新加载,只会做局部更新

**(3)、数据通过 AJAX 获取:**页面内容的更新通常是通过异步请求获取数据​这种方式的好处是用户体验更好,感觉更像使用原生应用。但同时也带来了路由管理的需求,这就是 Vue Router 要解决的问题

二、Vue Router 的基本使用

第一步:安装 Vue Router

首先,我们需要安装 Vue Router。如果你使用的是 Vue 3,那么需要安装 Vue Router 4:

bash 复制代码
npm install vue-router@4

如果你使用的是 Vue 2,那么需要安装 Vue Router 3:

bash 复制代码
npm install vue-router@3

第二步:创建路由器

安装完成后,我们需要创建一个路由器实例。通常我们会在 src/router/index.ts 文件中创建:

TypeScript 复制代码
// src/router/index.ts
import { createRouter, createWebHistory } from "vue-router";
import Home from "@/pages/Home.vue";
import News from "@/pages/News.vue";
import About from "@/pages/About.vue";

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/home",
      component: Home,
    },
    {
      path: "/news",
      component: News,
    },
    {
      path: "/about",
      component: About,
    },
  ],
});

export default router;

这里有几个关键点:

**1、createRouter:**创建路由实例的函数

**2、createWebHistory:**使用 HTML5 History 模式

**3、routers:**路由规则数组,每个规则包含 path(路径)和 component(组件)

第三步:注册路由器

创建好路由器后,我们需要在 Vue 应用中注册它:

bash 复制代码
// src/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");

第四步:使用路由

现在我们可以在组件中使用路由了。主要有两个组件:

**1、RouterLink:**用于创建导航链接

**2、RouterView:**用于渲染匹配的组件

html 复制代码
<template>
  <div class="app">
    <h2 class="title">Vue路由测试</h2>
    
    <!-- 导航区 -->
    <div class="navigate">
      <RouterLink to="/home" active-class="active">首页</RouterLink>
      <RouterLink to="/news" active-class="active">新闻</RouterLink>
      <RouterLink to="/about" active-class="active">关于</RouterLink>
    </div>
    
    <!-- 展示区 -->
    <div class="main-content">
      <RouterView></RouterView>
    </div>
  </div>
</template>

<script lang="ts" setup name="App">
import { RouterLink, RouterView } from "vue-router";
</script>

RouterLink 会被渲染成<a>标签,但它有一些特殊的功能:

**① to:**指定跳转的路径

**② active-class:**当路由激活时添加的CSS类

RouterView 是一个占位符,匹配的组件会在这里渲染

三、路由器工作模式

Vue Router 提供了两种工作模式:History 模式和 Hash 模式

1、History 模式

TypeScript 复制代码
const router = createRouter({
  history: createWebHistory(), // History 模式
  routes: [...]
});

优点:

① URL 更加美观,不带有 #

② 更接近传统的网站 URL

缺点:

① 项目上线时需要服务端配合处理路径问题

② 刷新页面可能会出现 404 错误

2、Hash 模式

TypeScript 复制代码
const router = createRouter({
  history: createWebHashHistory(), // Hash 模式
  routes: [...]
});

优点:

① 兼容性更好,不需要服务器端处理

② 刷新页面不会有 404 错误

缺点:

① URL 带有 # ,不太美观

② SEO 优化方面相对较差

选择建议

① 如果是内部管理系统,对 URL 美观度要求不高,可以使用 Hash 模式

② 如果是面向用户的网站,建议使用 History 模式,但需要后端配合

四、路由导航的三种方式

这是最常用的方式,通过 to 属性指定路径:

html 复制代码
<!-- 字符串写法 -->
<RouterLink to="/home">首页</RouterLink>

<!-- 对象写法 -->
<RouterLink :to="{ path: '/home' }">首页</RouterLink>

2、命名路由

给路由规则起个名字,可以简化跳转:

TypeScript 复制代码
// 路由配置
routes: [
  {
    name: "home", // 给路由命名
    path: "/home",
    component: Home
  }
]
bash 复制代码
<!-- 使用名字跳转 -->
<RouterLink :to="{ name: 'home' }">首页</RouterLink>

好处:

① 当路径发生变化时,不需要修改所有的跳转链接

② 配合参数传递更方便

3、编程式导航

有时候我们需要在 JavaScript 代码中进行页面跳转,这时候就需要使用编程式导航:

TypeScript 复制代码
import { useRouter } from "vue-router";

const router = useRouter();

// 字符串路径
router.push("/home");

// 对象形式
router.push({ path: "/home" });

// 命名路由
router.push({ name: "home" });

// 带参数
router.push({ 
  name: "newsDetail", 
  params: { id: 123 } 
});

五、路由传参详解

在实际开发中,我们经常需要在页面之间传递数据。Vue Router 提供了多种传参方式

1、Query 参数

Query 参数类似于 URL 中的查询字符串,格式为 ?key=value&key2=value2

传递参数:

html 复制代码
<!-- 字符串写法 -->
<RouterLink to="/news/detail?id=123&title=新闻标题">查看详情</RouterLink>

<!-- 对象写法 -->
<RouterLink :to="{
  path: '/news/detail',
  query: {
    id: 123,
    title: '新闻标题'
  }
}">查看详情</RouterLink>

接收参数:

TypeScript 复制代码
import { useRoute } from "vue-router";

const route = useRoute();
console.log(route.query.id); // 123
console.log(route.query.title); // '新闻标题'

2、Params 参数

Params 参数是路径的一部分,需要在路由规则中提前占位

配置路由规则:

TypeScript 复制代码
routes: [
  {
    name: "newsDetail",
    path: "/news/detail/:id/:title", // 占位符
    component: NewsDetail
  }
]

传递参数:

html 复制代码
<!-- 字符串写法 -->
<RouterLink to="/news/detail/123/新闻标题">查看详情</RouterLink>

<!-- 对象写法 -->
<RouterLink :to="{
  name: 'newsDetail', // 必须使用 name,不能用 path
  params: {
    id: 123,
    title: '新闻标题'
  }
}">查看详情</RouterLink>

接收参数:

TypeScript 复制代码
import { useRoute } from "vue-router";

const route = useRoute();
console.log(route.params.id); // 123
console.log(route.params.title); // '新闻标题'

3、Props 配置

为了让组件更方便地接收参数,Vue Router 提供了 props 配置:

TypeScript 复制代码
routes: [
  {
    name: "newsDetail",
    path: "/news/detail/:id/:title",
    component: NewsDetail,
    
    // 方式一:对象写法
    // props: { a: 1, b: 2 }
    
    // 方式二:布尔值写法,会把 params 参数作为 props 传递
    // props: true
    
    // 方式三:函数写法,可以自定义处理
    props(route) {
      return {
        id: route.params.id,
        title: route.params.title,
        timestamp: Date.now()
      };
    }
  }
]

然后在组件中就可以像使用普通 props 一样使用这些参数:

TypeScript 复制代码
// NewsDetail.vue
const props = defineProps({
  id: String,
  title: String,
  timestamp: Number
});

六、嵌套路由

嵌套路由是指在一个路由组件内部嵌套另一个路由组件。比如在新闻页面中嵌套新闻详情页面

1、配置嵌套路由

TypeScript 复制代码
const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: "/news",
      component: News,
      children: [ // 子路由配置
        {
          path: "detail/:id", // 子路径,注意不要加 /
          component: NewsDetail
        }
      ]
    }
  ]
});

2、在父组件中预留出口

html 复制代码
<!-- News.vue -->
<template>
  <div class="news">
    <div class="news-list">
      <RouterLink v-for="news in newsList" :key="news.id" 
                  :to="`/news/detail/${news.id}`">
        {{ news.title }}
      </RouterLink>
    </div>
    
    <!-- 子路由出口 -->
    <div class="news-content">
      <RouterView />
    </div>
  </div>
</template>

七、路由守卫

路由守卫允许我们在路由跳转前后执行一些操作,比如权限验证、数据加载等

1、全局守卫

TypeScript 复制代码
// router/index.ts

// 全局前置守卫
router.beforeEach((to, from, next) => {
  console.log('从', from.path, '跳转到', to.path);
  
  // 权限验证
  const isAuthenticated = localStorage.getItem('token');
  if (to.path === '/admin' && !isAuthenticated) {
    next('/login'); // 未登录,跳转到登录页
  } else {
    next(); // 继续跳转
  }
});

// 全局后置守卫
router.afterEach((to, from) => {
  console.log('跳转完成');
  // 可以在这里设置页面标题
  document.title = to.meta.title || '默认标题';
});

2、组件内守卫

TypeScript 复制代码
// 在组件中
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) => {
  console.log('离开路由前');
  next();
});

八、常见问题和解决方案

1、刷新页面出现 404 错误

**原因:**使用了 History 模式,但服务器没有正确配置

**解决方案:**开发环境,在 vite.config.ts 或 vue.config.js 中配置 base

2、路由参数变化时组件不重新渲染

**原因:**当路由参数变化时,Vue Router 会复用同一个组件实例

解决方案:

① 使用 watch 监听路由变化

② 使用 onBeforeRouteUpdate 钩子

③ 给组件添加 key 属性

TypeScript 复制代码
// 方案一:使用 watch
watch(
  () => route.params.id,
  (newId) => {
    // 处理逻辑
    fetchData(newId);
  }
);

// 方案二:使用 onBeforeRouteUpdate
onBeforeRouteUpdate((to) => {
  fetchData(to.params.id);
});

// 方案三:添加 key
<RouterView :key="$route.fullPath" />

3、路由守卫中如何正确使用 next ()

**常见错误:**忘记调用 next(),导致路由跳转被阻塞

正确用法:

TypeScript 复制代码
router.beforeEach((to, from, next) => {
  if (需要验证) {
    if (验证通过) {
      next(); // 继续跳转
    } else {
      next('/login'); // 重定向
    }
  } else {
    next(); // 一定要调用 next()
  }
});

希望这篇文章能帮助你更好地理解和使用 Vue Router,学习编程最好的方法就是动手实践,尝试使用 Vue Router 的各种特性,这样才能真正认识它

相关推荐
IT_陈寒17 小时前
Vue 3响应式原理深度拆解:5个90%开发者不知道的Ref与Reactive底层实现差异
前端·人工智能·后端
睡前要喝豆奶粉18 小时前
在.NET Core Web Api中使用JWT并配置UserContext获取用户信息
前端·.netcore
前端加油站18 小时前
一份实用的Vue3技术栈代码评审指南
前端·vue.js
计算机学姐21 小时前
基于SpringBoot的高校社团管理系统【协同过滤推荐算法+数据可视化】
java·vue.js·spring boot·后端·mysql·信息可视化·推荐算法
Jonathan Star1 天前
沉浸式雨天海岸:用A-Frame打造WebXR互动场景
前端·javascript
工业甲酰苯胺1 天前
实现 json path 来评估函数式解析器的损耗
java·前端·json
老前端的功夫1 天前
Web应用的永生之术:PWA落地与实践深度指南
java·开发语言·前端·javascript·css·node.js
LilySesy1 天前
ABAP+WHERE字段长度不一致报错解决
java·前端·javascript·bug·sap·abap·alv
Wang's Blog1 天前
前端FAQ: Vue 3 与 Vue 2 相⽐有哪些重要的改进?
前端·javascript·vue.js
再希1 天前
React+Tailwind CSS+Shadcn UI
前端·react.js·ui