【Vue】——路由

Vue 3 路由深入解析与实战指南

Vue Router 是 Vue.js 官方的路由管理器。它与 Vue.js 的核心深度集成,让用 Vue.js 构建单页面应用(SPA)变得轻而易举。本文将详细解析 Vue Router 4(用于 Vue 3)的核心概念和使用方法。

一、对路由的理解

什么是路由?

在传统的多页面网站中,每个页面(如 home.html, about.html)都是一个独立的文件。当用户点击链接时,浏览器会向服务器请求一个新的页面,这会导致整个页面刷新。

而在单页面应用(SPA)中,整个应用只有一个完整的页面(通常是 index.html)。路由 的核心作用就是:根据不同的浏览器地址(URL),动态地切换显示在这个"单页面"上的不同组件(Component),从而实现无需刷新页面的内容更新。

简单来说:路由建立了 URL 路径 与 要渲染的 Vue 组件 之间的映射关系。

工作流程:

  1. 用户点击页面上的路由链接。
  2. URL 地址栏的内容发生变化。
  3. 路由器(Vue Router)监测到这个变化。
  4. 路由器解析新的 URL,找到其配置规则中对应的组件。
  5. 路由器将旧的组件切换下去,将新的组件渲染到指定的路由出口(<router-view>)。

二、路由_基本切换效果

实现基本的路由切换需要三个核心步骤:

  1. 安装与引入 通过 npm 或 yarn 安装 Vue Router。

    复制代码
     npm install vue-router@4
  2. 定义路由规则 (routes) 创建一个路由器实例,并定义一组路由配置,每个配置都是一个映射关系。

复制代码
    // router/index.js
    import { createRouter, createWebHistory } from 'vue-router'
    import Home from '../views/Home.vue'
    import About from '../views/About.vue'

    const routes = [
      {
        path: '/', // 访问的路径
        name: 'Home', // 路由名称(可选)
        component: Home // 要渲染的组件
      },
      {
        path: '/about',
        name: 'About',
        component: About
      }
    ]

    const router = createRouter({
      history: createWebHistory(), // 指定历史模式
      routes // 路由规则配置
    })

    export default router
  1. 在应用中使用main.js 中挂载路由器实例,并在 App.vue 模板中使用 <router-link><router-view>

1、引入并使用路由器

复制代码
    // main.js
    import { createApp } from 'vue'
    import App from './App.vue'
    import router from './router'

    const app = createApp(App)
    app.use(router) // 挂载路由
    app.mount('#app')

在根组件引入并使用标签:routerview

使用routerlink给按钮绑定路径

active-class:激活后的类名

复制代码
    <!-- App.vue -->
    <template>
      <div id="app">
        <nav>
          <!-- 使用 router-link 组件进行导航 -->
          <!-- `to` 属性指定链接,它会被渲染成一个带有正确 `href` 的 `<a>` 标签 -->
          <router-link to="/">Home</router-link> |
          <router-link to="/about">About</router-link>
        </nav>
        <!-- 路由出口 -->
        <!-- 路由匹配到的组件将渲染在这里 -->
        <router-view />
      </div>
    </template>

效果: 点击 HomeAbout 链接,下方的 <router-view> 区域会无刷新地切换显示对应的组件内容。

三、路由_两个注意点

就看加没加routerlink

  1. 路由组件通常存放在 pagesviews 目录下,普通组件存放在 components 目录下。 这样做是为了更好地区分项目的组件结构,提高代码的可维护性。

  2. 通过路由切换时,被"隐藏"的路由组件实例是被 销毁(unmounted)了的,需要时再去 挂载(mounted)**。 这意味着组件的生命周期钩子(如 onMounted, onUnmounted)会随着导航的切换而触发。可以利用这一点来清除定时器、取消订阅等,防止内存泄漏。(就是一个路径切换到另一个路径)


拓展:如何区分路由组件和普通组件

定义header

使用header

现在header就是一般组件

下面的就是路由组件

Components:放一般组件

pages/views:放路由组件


关于第二个注意点可以调用两个生命周期测试

四、路由_路由器工作模式

Vue Router 有两种历史管理模式,通过 createRouter 的参数配置:

  1. createWebHistory (模式: 'history')

    • 创建的是正常的 URL,如 https://example.com/about
    • 美观,没有 # 符号。这样解释代#号的
    • 需要服务器支持 。因为SPA只有一个 index.html,如果用户直接访问 https://example.com/about 或刷新页面,服务器必须能正确地返回 index.html 文件,然后由 Vue Router 来处理路由。否则会返回 404 错误。(就像是配Nginx重定向路径一样)
  2. createWebHashHistory (模式: 'hash')

    • 创建的 URL 中包含一个哈希字符 #,如 https://example.com/#/about
    • 优点: 无需服务器配置。# 之后的内容变化不会发起新的网络请求,完全由前端控制。
    • 缺点: URL 看起来不美观,且 SEO 效果稍差(但现代爬虫已能很好处理)。

选择: 开发中通常使用 History 模式,部署时需要配置服务器;如果对服务器配置没有控制权,则使用 Hash 模式。

五、路由_to的两种写法

<router-link>to 属性有两种写法:

  1. 字符串写法 (简单路径)

    复制代码
     <router-link to="/home">Home</router-link>
     <router-link to="/about">About</router-link>
  2. 对象写法 (更强大,可以传参)

    复制代码
     <router-link :to="{ path: '/home' }">Home</router-link>
     <router-link :to="{ name: 'user', params: { id: 123 } }">User</router-link>
     <router-link :to="{ path: '/register', query: { plan: 'private' } }">Register</router-link>
复制代码

注意:对象写法必须使用 `v-bind`(即 `:`)绑定 `to` 属性。

六、路由_命名路由

在路由配置中,可以给任何路由提供一个 name 属性。

复制代码
const routes = [
  {
    path: '/user/:id',
    name: 'User', // 命名路由
    component: User
  }
]

这样做的好处是,在跳转时,可以绕过复杂的路径字符串,直接通过名称来引用路由。尤其是在路径很长或需要传递参数时非常方便。

三种方式都能跳转

复制代码
<!-- 通过名字导航 -->
<router-link :to="{ name: 'User', params: { id: 123 } }">User</router-link>

// 编程式导航
router.push({ name: 'User', params: { id: 123 } })

随着项目开发路径会越来越长,这时候后两种方法就更加适用

七、路由_嵌套路由 (子路由)

实际应用界面通常由多层嵌套的组件构成。例如,/user/profile/user/posts 都是在 /user 页面下的子视图。

使用 children 配置可以实现嵌套路由:

复制代码
// router/index.js
const routes = [
  {
    path: '/user/:id',
    component: User,
    children: [
      {
        // 当 /user/:id/profile 匹配成功
        // UserProfile 将被渲染到 User 的 <router-view> 内部
        path: 'profile', // 注意:不要加 `/`
        component: UserProfile
      },
      {
        path: 'posts',
        component: UserPosts
      },
      // 重定向到默认子路由
      {
        path: '',
        redirect: 'profile'
      }
    ]
  }
]

<!-- User.vue 组件 -->
<template>
  <div class="user">
    <h2>User {{ $route.params.id }}</h2>
    <router-link :to="{ name: 'UserProfile' }">Profile</router-link>
    <router-link :to="{ name: 'UserPosts' }">Posts</router-link>

    <!-- 子路由的出口 -->
    <router-view />
  </div>
</template>

案例:

父路由

子路由内容

添加子路径

使用routerview展示


useRouter:他是个hooks,使用他来添加参数

参数保存在query当中


前面代码完善:

父路由在routerlink后面添加参数发送数据,子路由接收数据router.query.xxx

routerlink第二种写法

第三种也可以写name


子路由接收数据可以换一种写法

解构router,注意点响应式数据结构之后会失去响应属性,要使用torefs

注意

to前面加:(这可能是省略的写法,比如value:to...)

双引号里面加反引号:是模版字符串然后就可以解析$(...)

关键点:

  • children 配置中的 path 不能以 / 开头,它是相对父路径的。
  • 必须在父级路由组件的模板中放置一个 <router-view> 来渲染子路由组件。

八、路由_query参数

Query 参数是附加在 URL 后面的键值对,以 ? 开头,用 & 分隔。例如:/register?plan=private&name=john

传递参数:

复制代码
<!-- 跳转并携带query参数,to的对象写法 -->
<router-link
  :to="{
    path: '/register',
    query: {
      plan: 'private',
      name: 'john'
    }
  }"
>Register</router-link>

接收参数: 在目标组件中,使用 useRoute 组合式 API 或 $route 对象来获取。

复制代码
<!-- 目标组件 Register.vue -->
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
// 在模板或JS中访问
console.log(route.query.plan) // 'private'
console.log(route.query.name) // 'john'
</script>

<template>
  <div>Plan: {{ route.query.plan }}</div>
  <div>Name: {{ route.query.name }}</div>
</template>

九、路由_params参数

Params 参数是定义在路由路径的一部分,属于 URL 本身。例如,路径 /user/123 中的 123 就是一个 params 参数。

修改vuerouter

使用params参数接收

重新写参数

参数的第二种写法


注意点:

一、不能用path(会自动忽略),只能使用name

错误写法

正确写法

二、不能传对象和数组

不能像下面这样传

三、加?是可选参数,传不传都可以


定义路由: 使用冒号 : 标记

复制代码
{
  path: '/user/:id', // 动态字段以冒号开始
  name: 'User',
  component: User
}

传递参数:

复制代码
<!-- 跳转并携带params参数,to的对象写法 -->
<!-- 注意:使用 params 时,不能使用 path,必须使用 name! -->
<router-link :to="{ name: 'User', params: { id: 123 } }">User 123</router-link>

接收参数: 与 Query 参数类似,通过 route.params 获取。

复制代码
<script setup>
import { useRoute } from 'vue-router'

const route = useRoute()
console.log(route.params.id) // '123'
</script>

<template>
  <div>User ID: {{ route.params.id }}</div>
</template>

注意: Params 参数是必需的。如果路由定义为 /user/:id,那么跳转到 /user 将会失败。可以使用可选操作符 ? 来指定一个参数是可选的:path: '/user/:id?'

十、路由_props配置

在组件中使用 $route 会使其与对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。props 配置可以将路由参数作为组件的 props 传递,使组件更易于复用和测试。

在路由配置中设置 props: true

props:true之后他会自动匹配参数

复制代码
{
  path: '/user/:id',
  name: 'User',
  component: User,
  props: true // 让路由组件可以通过props接收params参数
}

然后就可以使用defineprops()接收参数了

复制代码
<!-- User.vue 组件 -->
<script setup>
// 现在可以直接用 defineProps 接收,不再依赖 useRoute()
defineProps(['id'])
</script>

<template>
  <div>User ID: {{ id }}</div> <!-- 直接使用 prop -->
</template>

props 配置也可以是函数模式,允许你返回一个对象作为 props,非常适合处理静态值和 query 参数。

第一种写法只适用于params

第二种可以返回各种对象,然后取自己需要的

复制代码
{
  path: '/search',
  component: Search,
  props: (route) => ({ query: route.query.q, staticValue: 'hello' })
}

小结

使用这三种写法都是在<detail>路由组件后面继续加参数

十一、路由_replace属性

<router-link> 默认的导航行为是 push,它会在历史记录中添加一条新记录。

设置 replace 属性后,导航不会留下历史记录,而是替换掉当前的记录,相当于调用了 router.replace()。这意味着用户点击浏览器的后退按钮时,不能返回到上一个页面。

直接在routerlink里面添加 replace

如果想要不返回就添加replace,默认是push可以返回。

复制代码
<router-link to="/home" replace>Home</router-link>

十二、路由_编程式路由导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

<router-link> 最终会被转为a标签

<router-link>无法在script里面使用

在组件setup中,可以通过 useRouter 访问路由器实例。

核心方法:

  • router.push(location) :导航到一个新 URL,向 history 栈添加一条新记录。(与<router-link>里面的to一样的用法
  • router.replace(location):导航到一个新 URL,替换掉当前的 history 记录。
  • router.go(n) :在 history 记录中向前或向后移动多少步,类似 window.history.go(n)

功能是在首页3秒后跳到新闻页面

案例:给按钮绑定事件

给news限制属性(只能用限制的属性,防止写错)

复制代码
<script setup>
import { useRouter } from 'vue-router'

const router = useRouter()

const gotoHome = () => {
  router.push('/') // 字符串路径
}

const gotoUser = () => {
  router.push({ name: 'User', params: { id: 123 } }) // 对象形式
}

const replaceRegister = () => {
  router.replace({ path: '/register', query: { plan: 'private' } }) // 替换导航
}

const goBack = () => {
  router.go(-1) // 等同于 history.back()
}
</script>

<template>
  <button @click="gotoHome">Go Home</button>
  <button @click="gotoUser">Go to User 123</button>
  <button @click="replaceRegister">Replace to Register</button>
  <button @click="goBack">Go Back</button>
</template>

十三、路由_重定向

重定向也是通过 routes 配置来完成。

语法: { path: 原始路径, redirect: 目标路径 }

在router文件中再添加一个首页的重定向

复制代码
const routes = [
  {
    path: '/home',
    redirect: '/' // 访问 /home 时,重定向到 /
  },
  {
    path: '/old-news',
    redirect: '/news' // 访问 /old-news 时,重定向到 /news
  },
  {
    path: '/search',
    redirect: (to) => {
      // 函数方式动态返回重定向目标
      return { path: '/search-results', query: { q: to.query.keyword } }
    }
  },
  // 一种常见的用法:访问根路径时重定向到首页
  {
    path: '/',
    redirect: '/home'
  }
]

总结

Vue Router 是构建 Vue 3 单页面应用的基石。通过理解和掌握上述知识点------从基本配置、两种参数传递、嵌套路由,到更高级的编程式导航、Props 解耦和工作模式------你将能够构建出结构清晰、用户体验流畅的复杂单页应用。务必在实践中多加运用,以融会贯通。

相关推荐
羊羊小栈4 小时前
基于「多模态大模型 + BGE向量检索增强RAG」的航空维修智能问答系统(vue+flask+AI算法)
vue.js·人工智能·python·语言模型·flask·毕业设计
喝拿铁写前端4 小时前
Vue 组件通信的两种世界观:`.sync` 与普通 `props` 到底有什么不同?
前端·vue.js·前端框架
用户22152044278004 小时前
vue3组件间的通讯方式
前端·vue.js
tyro曹仓舒5 小时前
Vue单文件组件到底需不需要写name
前端·vue.js
閞杺哋笨小孩6 小时前
Vue3 点击指令(防抖 / 节流)
前端·vue.js
岁月宁静6 小时前
AI 语音合成技术实践:实现文本转语音实时流式播放
前端·vue.js·node.js
閞杺哋笨小孩6 小时前
Vue3 可拖动指令(draggable)
前端·vue.js
Mintimate6 小时前
Vue项目接口防刷加固:接入腾讯云天御验证码实现人机验证、恶意请求拦截
前端·vue.js·安全
练习前端两年半6 小时前
🚀 Vue3按钮组件Loading状态最佳实践:优雅的通用解决方案
前端·vue.js·element