文章目录
- 引语
- [一、 快速落地:Vue Router 4 基础配置与骨架搭建](#一、 快速落地:Vue Router 4 基础配置与骨架搭建)
- [二、 架构抉择:深度解密 Hash 与 History 两种工作模式](#二、 架构抉择:深度解密 Hash 与 History 两种工作模式)
-
- [2.1 Hash 模式](#2.1 Hash 模式)
- [2.2 History 模式](#2.2 History 模式)
- [2.3 Hash 模式与 History 模式多维对比](#2.3 Hash 模式与 History 模式多维对比)
- [三、 声明式导航升级:组件 `<router-link>` 与命名路由](#三、 声明式导航升级:组件
<router-link>与命名路由) -
- [3.1 字符串写法 vs 对象写法](#3.1 字符串写法 vs 对象写法)
- [3.2 企业级规范:命名路由(Named Routes)](#3.2 企业级规范:命名路由(Named Routes))
- [四、 结构进化:嵌套路由(Nested Routes)的多层页面设计](#四、 结构进化:嵌套路由(Nested Routes)的多层页面设计)
- [五、 数据传递核心:Query 传参与 Params 传参的生死博弈](#五、 数据传递核心:Query 传参与 Params 传参的生死博弈)
-
- [5.1 Query 参数(查询字符串)](#5.1 Query 参数(查询字符串))
- [5.2 Params 参数(路径参数)](#5.2 Params 参数(路径参数))
- [六、 解耦技巧:路由的 Props 配置](#六、 解耦技巧:路由的 Props 配置)
- [七、 动态掌控力:Replace 属性与编程式导航](#七、 动态掌控力:Replace 属性与编程式导航)
-
- [7.1 `replace` 属性的妙用](#7.1
replace属性的妙用) - [7.2 编程式导航(Programmatic Navigation)](#7.2 编程式导航(Programmatic Navigation))
- [7.1 `replace` 属性的妙用](#7.1
- 结语
引语
在传统的前端开发模式中,一个特定的URL地址通常对应着服务器上的一个独立HTML页面。当用户在浏览器中切换地址时,浏览器会向服务器发送全新的请求,并重新加载、刷新整个页面。
但在现代Web开发中,基于Vue构建的单页面应用打破了这一常态。在单页面架构中,整个项目在运行期间通常只包含一份HTML文件。当页面内容发生切换时,应用并不会重新向服务器请求新页面,而是通过前端动态地卸载旧组件、挂载新组件来实现。
为了优雅、高效地管理这些组件之间的切换逻辑,Vue官方推出了核心路由管理器------Vue Router 。从本质上来说,前端路由系统就是建立URL地址与组件之间的映射关系。
一、 快速落地:Vue Router 4 基础配置与骨架搭建
在Vue 3项目中,我们通常使用Vue Router来搭建路由骨架。创建并实例化一个路由器对象,需要借助官方提供的 createRouter 方法。
它的基本结构配置如下:
js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
// 创建路由器实例
const router = createRouter({
history: createWebHistory(), // 指定路由工作模式
routes: [ // 配置路由规则映射表
{
path: '/',
component: Home
},
{
path: '/about',
component: About
}
]
})
export default router
在 createRouter() 的配置对象中,最核心的两个选项分别是:
history:用于明确指定路由器底层采用什么样的工作模式。routes:用于维护一个路由规则数组,每一个对象都代表了一条"路径到组件"的映射线。例如,当访问根路径/时渲染Home组件,访问/about时渲染About组件。
二、 架构抉择:深度解密 Hash 与 History 两种工作模式
Vue Router 提供了两种最常见的工作模式,它们在 URL 表现形式、底层运作机制以及线上部署要求上面有着本质的区别。
2.1 Hash 模式
- 创建方式 :使用
createWebHashHistory()。 - 表现形式 :URL 中会夹杂一个
#符号,形如http://localhost:5173/#/home。 - 运作原理 :
#及其后面的部分被称为 Hash 值。浏览器拥有一个特性:修改 URL 中的 Hash 值时,绝不会向服务器重新发送网络请求 。Vue Router 利用这一特性,通过监听浏览器的hashchange事件,即可捕获路径变化并动态替换组件。 - 优缺点 :优点是极其简单,对后端服务器没有任何特殊要求,开箱即用。缺点是路径中带
#不够美观,对搜索引擎抓取不够友好。
2.2 History 模式
- 创建方式 :使用
createWebHistory()。 - 表现形式 :URL 与传统多页面网站完全一致,形如
http://localhost:5173/home。 - 运作原理 :基于 HTML5 标准提供的 History API(如
pushState和replaceState)来实现无需刷新的页面路径变更。 - 致命痛点 :由于去掉了
#,路径看起来像一个真实的服务器资源地址。如果用户在http://localhost:5173/user页面上手动执行刷新 ,浏览器会固执地直接向服务器请求/user这个独立的物理资源。若服务器没有配置任何重定向规则,便会直接抛出 404 错误 。因此,History 模式上线部署时,必须依赖后端服务器进行额外配置,将所有未匹配到的资源重定向到index.html。
2.3 Hash 模式与 History 模式多维对比
| 对比维度 | Hash 模式 | History 模式 |
|---|---|---|
| URL 表现 | 带有 # 符号(如 /#/about) |
无 # 符号,干净整洁(如 /about) |
| 美观程度 | 一般,略显冗余 | 较好,符合现代 Web 审美 |
| SEO 支持 | 较差 | 较好 |
| 服务器配置 | 完全不需要额外处理 | 必须配置,否则刷新页面报 404 |
| 企业选择 | 多用于内网系统、轻量工具 | 企业级商业项目优先推荐 |
三、 声明式导航升级:组件 <router-link> 与命名路由
在 Vue Router 中,我们很少直接编写原生的 <a> 标签来进行跳转。官方提供了专用的 <router-link> 内置组件。
3.1 字符串写法 vs 对象写法
最基础的声明式导航使用 to 属性指定字符串路径:
js
<router-link to="/home">首页</router-link>
然而在真实项目开发中,更推荐使用动态绑定对象的写法:
js
<router-link :to="{ path: '/home' }">首页</router-link>
核心优势:对象写法拥有极强的可扩展性,它是后续在导航中携带参数(Query 或 Params)的必备前提。
3.2 企业级规范:命名路由(Named Routes)
随着项目规模和复杂度的不断攀升,我们的页面路径往往会变得非常冗长且层级复杂,例如 /admin/user/setting/profile。如果我们在业务代码中硬编码堆砌这些路径字符串,一旦未来产品经理提出路径调整需求,维护成本将令人崩溃。
此时,命名路由 便是最佳解法。我们可以在配置项中为路由规则赋予一个唯一的 name 属性:
js
{
path: '/user/detail/info/secure',
name: 'userInfo',
component: UserInfo
}
在组件中进行跳转时,直接绑定 name 即可:
js
<router-link :to="{ name: 'userInfo' }">用户安全中心</router-link>
这样一来,无论底层的 path 如何演变,只要 name 保持不变,所有的跳转代码均无需任何修改,大大增强了系统的健壮性。
四、 结构进化:嵌套路由(Nested Routes)的多层页面设计
真实的中后台管理系统往往拥有多层嵌套的复合页面结构:
text
个人中心
├─ 我的订单
├─ 我的收藏
└─ 我的地址
在 Vue Router 中,我们通过配置 children 属性来实现多级嵌套关系。
js
{
path: '/user',
component: UserLayout, // 父骨架组件
children: [
{
path: 'order', // 子路由路径:前方切勿加 "/" 符号!
component: Order
},
{
path: 'collect',
component: Collect
}
]
}
避坑关键点 :配置
children内部的子路由时,子路径(如order)前面千万不要加/。如果加了/,Vue Router 会将其视为根路径,从而脱离原有的层级关系。
在编写好映射规则后,还需要在父组件(如 UserLayout.vue)的模板内部预留一个 <router-view /> 占位插槽 。当浏览器地址切换至 /user/order 时,Order 子组件就会自动填充渲染到父组件的 <router-view /> 内部。
五、 数据传递核心:Query 传参与 Params 传参的生死博弈
页面间的通信和参数传递是前端业务开发中最频繁出现的需求。Vue Router 为我们提供了两套各司其职的传参技术方案。
5.1 Query 参数(查询字符串)
-
核心本质 :等同于传统 HTTP 请求中的 URL 查询字符串(形如
/user?id=1&name=Tom)。 -
发送方式:
js<router-link :to="{ path: '/user', query: { id: 1, name: 'Tom' } }">用户信息</router-link> -
接收方式:
jsimport { useRoute } from 'vue-router' const route = useRoute() console.log(route.query.id, route.query.name) -
技术特点 :不需要提前在路由映射表里修改
path占位;参数完全暴露在浏览器的地址栏中;最大的优势是刷新页面时参数绝对不会丢失。
5.2 Params 参数(路径参数)
-
核心本质 :属于 RESTful 风格的路径段落参数(形如
/user/1/Tom)。 -
规则配置 :必须在路由表里通过
:符号提前进行参数占位。js{ path: '/user/:id/:name', name: 'user', component: User } -
发送方式:
js<router-link :to="{ name: 'user', params: { id: 1, name: 'Tom' } }">用户信息</router-link> -
接收方式:
jsconst route = useRoute() console.log(route.params.id) -
致命规矩:
当使用动态对象写法传递
params参数时,只能配合name(命名路由)进行跳转,绝对不允许配合path写法! 例如:to="{ path: '/user', params: {...} }"会导致参数无法正确传递,这是新手开发中最容易踩中的盲区。此外,Params 传参必须提前做好占位,若不配置占位,数据无法正确接收。
六、 解耦技巧:路由的 Props 配置
在常规开发中,我们在组件内部为了拿到路由参数,往往不得不编写类似 const route = useRoute(); const id = route.params.id; 的代码。这样做的弊端非常明显:当前的组件与路由系统发生了深度强耦合。一旦未来这个组件需要被挪移到其他没有路由的环境下复用,就无法正常运转。
为了彻底打破这种耦合,Vue Router 提供了优雅的 props 配置功能。
js
{
path: '/user/:id',
component: User,
props: true // 开启布尔值模式:自动将 params 中的参数转换为组件的 Props 属性
}
在 User.vue 组件中,我们不需要再调用 useRoute(),直接声明并接收 props 即可:
js
<script setup>
// 直接接收,就像普通的父子组件传值一样,组件瞬间变得干净、高内聚
defineProps(['id'])
</script>
<template>
<div>当前用户 ID 是:{{ id }}</div>
</template>
七、 动态掌控力:Replace 属性与编程式导航
7.1 replace 属性的妙用
默认情况下,无论是点击 <router-link> 还是触发页面切换,路由系统都会向浏览器的历史记录栈中追加(push)一条新记录。
例如,用户操作的轨迹是 页面A → 页面B → 页面C。如果此时用户点击浏览器的返回按钮,其回溯路线是 页面C → 页面B → 页面A。
但在某些特定业务场景下(如"登录页登录成功后跳转到首页",或者"支付成功后跳转到结果页"),我们不希望用户能够通过返回键退回到刚才的登录或支付页。此时我们只需为组件附加 replace 属性:
js
<router-link replace to="/home">进入首页</router-link>
它在底层对应的是 history.replaceState() 接口,作用是直接替换当前的历史记录,而不是像以往一样去新增记录,完美防范了不合理的退回操作。
7.2 编程式导航(Programmatic Navigation)
除了利用模板里的 <router-link> 点击标签引发跳转外,在实际研发中,我们海量的业务逻辑都需要在 JavaScript 代码中控制跳转。比如"表单校验通过后跳转"、"Ajax 请求完毕后跳转"。
在 Vue 3 组合式 API 中,我们调用 useRouter() 钩子来获取全局路由操作实例:
js
import { useRouter } from 'vue-router'
const router = useRouter() // 获取操作实例
// 各种灵活的控制手段:
router.push('/home') // 向历史栈追加记录并跳转
router.replace('/home') // 替换当前记录并跳转
router.back() // 后退一步
router.forward() // 前进一步
router.go(-2) // 任意步数的前进或后退(例如后退两步)
结语
掌握 Vue Router 的核心基础,是前端开发由"页面组装"迈向"应用架构"的分水岭。需要深刻理清 Hash 与 History 的底层逻辑 、切实避开 Params 传参的语法红线 、灵活玩转编程式导航与解耦 Props,我们才能在开发中真正建立起成熟、完整的单页面路由认知体系,并为后续进阶学习打下牢不可破的底层基础。