单页应用程序与前端路由

单页应用程序概述

单页应用程序(Single Page Application,简称 SPA)是指所有的功能都在一个HTML页面上实现的应用程序。在基于Vue等现代前端框架开发网站时,构建出的完整网站应用通常都属于单页应用程序。

  • 核心特征:整个应用仅包含一个完整的HTML页面,页面加载后,通过JavaScript动态更新页面内容,而不会重新加载整个页面。
  • 典型代表:网易云音乐Web端等现代Web应用。

单页应用与多页应用的区别

与单页应用相对应的是多页应用程序(Multi-Page Application,简称 MPA),如传统的京东、淘宝等电商网站。两者在页面切换时的表现存在本质差异:

  1. 单页应用(SPA)的页面切换

    • 切换内容时,公共部分(如顶部导航栏)不会刷新,保持复用状态。
    • 仅对需要更新的内容区域进行局部替换和渲染。
    • 整个过程在同一个HTML页面内完成,无页面跳转的白屏现象。
  2. 多页应用(MPA)的页面切换

    • 每次点击链接或切换标签页,都会跳转到一个新的页面
    • 整个页面(包括公共导航区域)都会进行重新加载和渲染
    • 页面与页面之间相互独立,切换时伴随完整的HTTP请求和页面刷新。

页应用与多页应用的优缺点对比

1. 单页应用(SPA)的优缺点

  • 优点
    • 性能较高:采用按需更新机制,仅替换需要变化的组件或结构,避免了整页刷新带来的性能损耗。
    • 开发效率高:支持组件化开发,可将页面公共部分和独立模块封装为组件,像替换零件一样进行组合与切换。
    • 用户体验好:页面切换流畅,无刷新白屏,交互体验接近原生桌面或移动应用。
  • 缺点
    • 学习成本较高:需要额外学习前端路由等相关概念和语法。
    • 首屏加载较慢:由于单个HTML页面包含了整个网站的所有基础资源,初次加载时需要下载较多文件,导致首屏渲染速度相对较慢(可通过路由懒加载等方案优化)。
    • SEO(搜索引擎优化)不友好:由于内容多由JavaScript动态渲染,且只有一个HTML入口,搜索引擎爬虫难以抓取完整内容,搜索权重较低。

2. 多页应用(MPA)的优缺点

  • 优点
    • 首屏加载快:每次仅加载当前页面相关的资源,初始加载速度快。
    • SEO友好:每个页面都有独立的HTML文件和URL,搜索引擎爬虫易于抓取,有利于提升搜索排名。
  • 缺点
    • 性能与体验受限:页面切换需要重新加载公共资源,存在刷新延迟,用户体验不如单页应用。
    • 开发效率相对较低:公共代码的复用和状态管理不如单页应用的组件化方案便捷。

应用场景与选型指南

在实际开发中,应根据项目的具体需求选择合适的架构模式:

  1. 单页应用(SPA)适用场景

    • 系统管理类网站:如后台管理系统、企业内部办公系统。
    • 内部工具与文档网站:对SEO无要求,侧重于交互性能和开发效率。
    • 移动端Web站点:移动端对页面切换的流畅度和用户体验要求极高,且首屏加载慢的问题可通过按需加载等技术方案有效解决。
  2. 多页应用(MPA)适用场景

    • 企业对外官方网站:代表企业形象,要求首屏加载极快,且需要良好的SEO支持以便被用户搜索到。
    • 大型电商类网站:对搜索引擎收录和首屏打开速度有严格要求。

前端路由核心概念

单页应用能够实现按需更新的核心在于明确访问路径组件之间的对应关系。这一对应关系的维护依赖于路由(Router)

1. 路由的本质

  • 路由本质上是一种映射关系
  • 生活中的路由:在计算机网络中,路由器维护的是设备与IP地址之间的映射关系。当设备连接网络时,路由器为其分配IP,并通过该IP进行数据包的准确转发与接收。
  • 前端中的路由:在前端开发中,路由维护的是URL路径与视图组件之间的映射关系。

2. Vue中的路由映射
在Vue单页应用中,路由专门用于记录和管理路径(Path)组件(Component) 的一一对应关系。

  • 映射规则示例
    • 访问路径 /home 映射并渲染 Home 组件。
    • 访问路径 /comment 映射并渲染 Comment 组件。
    • 访问路径 /search 映射并渲染 Search 组件。
  • 工作机制:当用户切换不同的URL路径时,Vue Router会根据配置的映射关系,动态地将对应的组件渲染到页面的指定区域,从而实现页面的局部更新。

知识小结

  1. 什么是单页应用程序(SPA)?
    • 所有的功能都在一个HTML页面上实现的应用程序。
  2. 单页应用的优缺点是什么?
    • 优点:按需更新、性能高、开发效率高、用户体验好。
    • 缺点:学习成本高、首屏加载慢、不利于SEO。
  3. 单页应用的主要应用场景有哪些?
    • 系统类网站、企业内部网站、文档类网站以及对性能要求高的移动端站点。
  4. 什么是路由?
    • 路由是一种映射关系。在Vue中,路由特指访问路径组件之间的映射关系,是实现单页应用按需更新的核心机制。

Vue Router 基础教程(基于 Vue 2)

在前端单页面应用(SPA)中,路由本质上是路径(Path)与组件(Component)之间的映射关系。当浏览器地址栏的路径发生变化时,页面需要根据预设的映射关系切换展示对应的组件,从而实现无刷新的页面视图更新。

Vue Router 插件简介

Vue Router 是 Vue.js 官方提供的路由管理插件。其核心作用是监听地址栏路径的变化,并根据映射规则自动切换显示对应的组件。

版本兼容性说明
在学习和使用 Vue 生态插件时,需严格注意版本对应关系(可记忆为“233”与“344”原则):

  • Vue 2 项目:对应使用 Vue Router 3.x 版本(当前稳定版为 3.6.5)与 Vuex 3.x 版本。
  • Vue 3 项目:对应使用 Vue Router 4.x 版本与 Vuex 4.x(或 Pinia)版本。

本教程基于 Vue 2 环境,因此使用 Vue Router 3.6.5 版本。

Vue Router 核心使用步骤

Vue Router 的完整使用流程可归纳为 “5+2”步骤,即 5 个固定的基础初始化步骤和 2 个动态的核心业务配置步骤。

基础初始化步骤(固定 5 步)

1. 下载插件

在终端中执行 npm 命令安装指定版本的 Vue Router。

1
npm i vue-router@3.6.5
2. 引入插件

在项目的入口文件(通常为 main.js)中导入 Vue Router。

1
import VueRouter from 'vue-router'
3. 安装注册插件

Vue 相关的插件在使用前必须通过 Vue.use() 进行全局安装与注册。该操作会在内部完成插件的初始化及全局组件的注册。

1
Vue.use(VueRouter)
4. 创建路由实例对象

使用 VueRouter 构造函数创建一个路由实例对象。初始阶段可先创建一个空对象,后续再配置具体规则。

1
const router = new VueRouter()
5. 注入 Vue 实例

将创建好的路由实例对象注入到 Vue 根实例中,建立路由与 Vue 应用的关联。注入后,Vue 实例将被路由接管,浏览器地址栏会自动追加 #/(Hash 模式标志)。

1
2
3
4
new Vue({
router, // 等同于 router: router
render: h => h(App)
}).$mount('#app')

注意:为实现对象属性的简写,建议将路由实例变量严格命名为 router

核心业务配置步骤(动态 2 步)

1. 创建视图组件并配置路由规则

创建视图组件
与常规的可复用组件(存放于 components 目录)不同,路由切换的页面级组件推荐存放于 views 目录中。
src/views 目录下创建以下三个组件:

  • Find.vue(发现音乐)
  • My.vue(我的音乐)
  • Friend.vue(朋友)

ESLint 规范处理:若项目开启了 ESLint,组件名必须由多个单词组成(如 FindMusic)以避免与 HTML 原生标签冲突。若使用单单词命名,需在组件内部显式声明 name 属性以消除报错:

1
2
3
4
5
<script>
export default {
name: 'FindMusic'
}
</script>

配置路由规则
main.js 中导入视图组件,并在创建路由实例时通过 routes 属性配置映射规则。routes 是一个数组,每个元素代表一条路由规则,包含 path(路径)和 component(组件)两个核心属性。

1
2
3
4
5
6
7
8
9
10
11
import Find from './views/Find.vue'
import My from './views/My.vue'
import Friend from './views/Friend.vue'

const router = new VueRouter({
routes: [
{ path: '/find', component: Find },
{ path: '/my', component: My },
{ path: '/friend', component: Friend }
]
})

注意:path 属性配置的是绝对路径(以 / 开头),切勿写成相对路径。

2. 配置导航链接与路由出口

配置导航链接
在模板中配置导航菜单。在 Hash 模式下,需通过 <a> 标签的 href 属性修改哈希路径(带 # 前缀)来触发路由切换。

1
2
3
<a href="#/find">发现音乐</a>
<a href="#/my">我的音乐</a>
<a href="#/friend">朋友</a>

配置路由出口
使用 Vue Router 内置的 <router-view> 组件作为路由出口。该组件的作用是占位,用于控制匹配组件的最终渲染位置。

1
2
3
4
5
6
7
8
9
<!-- 导航区域 -->
<nav>
<a href="#/find">发现音乐</a>
<a href="#/my">我的音乐</a>
<a href="#/friend">朋友</a>
</nav>

<!-- 路由出口:匹配的组件将在此处渲染 -->
<router-view></router-view>

通过调整 <router-view> 在 DOM 结构中的位置,可以灵活控制视图组件展示在导航栏的上方、下方或其他任意区域。

总结与回顾

Vue Router 的核心使用流程可总结为以下结构:

  1. 基础初始化(固定 5 步)

    • 下载插件(注意 Vue 2 对应 3.x 版本)。
    • 引入插件。
    • 使用 Vue.use() 安装注册。
    • 创建 VueRouter 实例对象。
    • 将实例注入 Vue 根实例。
  2. 核心业务配置(动态 2 步)

    • 建组件、配规则:在 views 目录创建页面组件,在 routes 数组中配置 pathcomponent 的映射关系。
    • 配导航、配出口:使用 <a> 标签配置带 # 的哈希链接修改路径,使用 <router-view> 组件指定视图渲染位置。

掌握上述“5+2”步骤,即可完成 Vue 2 项目中基础路由的搭建与单页面应用的视图切换。

Vue 组件分类与目录存放规范

组件的本质与分类概述

在 Vue 项目中,所有的组件本质上都是 .vue 单文件组件,在技术实现和底层解析上并无区别。然而,为了提升项目的可维护性和代码的清晰度,在实际开发中通常会根据组件的业务职责和使用场景将其划分为两类:

  1. 页面型组件
  2. 复用型组件

页面型组件与存放规范

页面型组件通常代表应用中的一个完整页面或核心视图模块。这类组件的主要特征是配合 Vue Router(路由) 进行视图的切换与渲染。

  • 典型场景:首页、列表页、分类页、个人中心等整体页面。
  • 存放目录:统一存放在项目的 views 目录下。
  • 使用方式:在路由配置文件中引入,并作为路由的 component 属性值进行挂载。

复用型组件与存放规范

复用型组件通常是指页面内部的具体功能模块或 UI 组件。这类组件的主要特征是在同一个页面或跨多个页面中被多次重复使用,用于展示特定数据或实现特定交互。

  • 典型场景:商品卡片、评价列表、导航栏、分页器等局部模块。
  • 存放目录:统一存放在项目的 components 目录下。
  • 使用方式:在需要使用的页面型组件或其他复用型组件中通过 import 引入,并注册为局部组件或全局组件。

目录分类的核心目的

虽然页面型组件和复用型组件在本质上都是 .vue 文件,不按照规范存放也不会导致程序运行报错,但严格遵循目录分类规范具有以下核心目的:

  1. 提升可维护性:使项目结构更加清晰,开发者能够快速定位页面视图或公共组件。
  2. 职责分离:明确区分路由级视图与局部复用模块,降低代码耦合度。
  3. 团队协作:形成约定俗成的开发规范,降低团队沟通与协作成本。

案例分析与实战练习

通过以下实际业务场景,进一步理解组件的分类与存放规则:

案例一:应用的主页面切换

  • 场景描述:应用底部包含导航栏,点击不同导航项时,上方主体区域会切换显示“首页(Home)”或“分类页(Category)”。
  • 组件分析:此类组件负责整个主体区域的视图切换,需配合路由使用。
  • 分类与存放:属于页面型组件,应存放在 views 目录中(例如 views/Home.vueviews/Category.vue)。

案例二:应用内的局部模块

  • 场景描述:在首页和分类页中,均需要展示“商品卡片(Product)”和“用户评价(Comment)”模块,且这些模块在页面中会被多次渲染。
  • 组件分析:此类组件属于页面内部的局部模块,具有高度的复用性。
  • 分类与存放:属于复用型组件,应存放在 components 目录中(例如 components/Product.vuecomponents/Comment.vue)。

本章小结

  1. 组件分类:Vue 组件主要分为页面型组件复用型组件
  2. 本质相同:两者本质上均为 .vue 文件,技术上无差异。
  3. 存放规范
    • 配合路由使用的页面型组件存放在 views 目录。
    • 用于数据展示和多次复用的复用型组件存放在 components 目录。
  4. 分类目的:核心目标是便于项目维护,保持代码结构清晰。在实际开发中,应严格遵守此约定俗成的目录规范。

Vue2 路由模块的抽离与封装

背景与目标

在前序课程中,已经掌握了 Vue Router 插件的基本使用。在初始开发阶段,所有的路由配置(包括组件导入、插件初始化、路由规则配置等)通常默认编写在 main.js 文件中。

随着项目规模的扩大,导入的组件和配置的路由规则会不断增加。如果将所有路由相关代码继续堆积在 main.js 中,会导致主文件过于臃肿,严重降低代码的可读性与可维护性。

因此需要将路由模块从 main.js 中抽离出来,封装为独立的路由模块文件。通过模块拆分,可以使主文件更加简洁清晰,同时提升项目的整体可维护性。

核心步骤

路由模块的抽离与封装主要分为以下四个核心步骤:

创建路由模块文件

在项目的 src 目录下,新建一个名为 router 的文件夹,并在该文件夹内创建 index.js 文件。此文件将作为独立的路由模块,专门用于存放和管理所有路由相关的配置。

迁移路由配置代码

main.js 中与路由相关的代码全部剪切,并粘贴至 src/router/index.js 文件中。需要迁移的代码主要包括:

  • 页面组件的导入语句
  • VueRouter 插件的导入语句
  • Vue.use(VueRouter) 插件安装与初始化语句
  • 路由实例的创建及路由规则的配置

补充导入与导出语句

代码迁移后,需要在 src/router/index.js 中补充必要的导入与导出逻辑,以保证模块的独立性与可用性:

  • 补充 Vue 导入:由于代码脱离了 main.js 环境,需在新文件顶部补充 import Vue from 'vue',以确保 Vue.use() 能够正常执行。
  • 导出路由实例:在文件末尾使用 export default router 将创建好的路由实例导出,以便主文件能够引入并使用。

在主文件中引入并挂载路由

main.js 中,删除原有的路由配置代码,改为导入新封装的路由模块,并将其注入到 Vue 根实例中:

  • 使用 import router from './router' 导入路由模块。
  • new Vue() 实例化时,将 router 挂载到配置对象中。

路径问题与优化方案

相对路径失效问题

在完成代码迁移后,项目运行时可能会抛出 Module not found(模块未找到)的错误。这是因为 index.js 文件所在的目录层级发生了变化,导致组件的相对导入路径失效

例如,原路径 ./views/Find 是基于 main.js(位于 src 目录下)计算的。当代码迁移至 src/router/index.js 后,基准目录变为 router,此时继续使用 ./views/Find 会找不到目标文件。临时解决方案是将路径修改为 ../views/Find,即先回退到上一级目录再进行查找。

使用绝对路径标识符 @

使用相对路径(如 ../)在文件层级较深时会导致代码难以维护。在 Vue CLI 脚手架环境中,推荐使用绝对路径标识符 @ 来优化组件的引入方式。

  • 标识符含义@ 符号默认指向项目的 src 目录。
  • 使用方式:将组件导入路径修改为 @/views/Find@/views/My
  • 核心优势:使用 @ 标识符后,路径查找将直接从 src 目录出发,与当前文件所处的层级无关。这不仅避免了因文件移动导致的路径错误,还大幅提升了代码的编写效率与可维护性。

路由模块封装总结

  1. 路由模块封装的意义:将路由核心代码提取至 src/router/index.js,实现了代码的模块化拆分,使 main.js 更加简洁,显著提升了项目的可维护性。
  2. 模块封装的关键代码:在独立路由模块中,必须确保正确导入 Vue 以安装插件,并使用 export default 导出路由实例。
  3. 组件引入的最佳实践:在脚手架环境中,强烈推荐使用 @ 标识符指代 src 目录。通过绝对路径引入组件,可以有效规避目录层级变动带来的路径解析错误。

Vue Router 导航链接与高亮机制

需求分析与传统实现方案

在单页面应用开发中,导航菜单的高亮效果是常见需求。当用户点击某个导航项时,该导航项需要呈现高亮状态,以指示当前所处的模块。

传统实现方案的痛点

如果使用原生的 a 标签结合 JavaScript 手动实现高亮,需要编写大量逻辑代码:

  • 监听导航项的点击事件。
  • 移除上一个高亮导航项的激活类名。
  • 为当前点击的导航项添加激活类名。

这种方式不仅代码繁琐,而且不利于后期维护。

Vue Router 的解决方案

Vue Router 提供了一个全局组件 router-link,用于替代原生的 a 标签。它不仅能够实现路由跳转,还能自动处理导航高亮,无需编写额外的 JavaScript 代码。

替换原生 a 标签

在模板中,将原有的 a 标签替换为 router-link 标签。

配置 to 属性

router-link 不使用 href 属性,而是使用 to 属性来指定目标路由路径。

  • 必填项to 属性是必填项,若未配置或配置错误,控制台会抛出 missing required prop: "to" 错误。
  • 路径格式to 属性的值直接填写路由路径(如 /discover),无需添加 #(在 Hash 模式下,原生 a 标签需要加 #)。
  • 渲染结果router-link 在底层最终依然会被渲染为原生的 a 标签,但其 href 属性会由 Vue Router 自动计算并生成。

代码示例:

1
2
3
4
5
<!-- 传统 a 标签写法 -->
<a href="#/discover">发现音乐</a>

<!-- router-link 写法 -->
<router-link to="/discover">发现音乐</router-link>

自动添加激活类名

当路由匹配成功时,router-link 会自动为其渲染出的 a 标签添加特定的 CSS 类名。开发者只需在样式表中定义这些类名的样式,即可实现高亮效果。

默认情况下,Vue Router 会添加以下两个类名:

  • router-link-active
  • router-link-exact-active

样式配置示例

在 CSS 中直接针对自动添加的类名编写样式:

1
2
3
4
5
/* 当导航项被激活时,改变背景颜色 */
.router-link-active {
background-color: purple;
color: white;
}

模糊匹配与精确匹配的区别

router-link 自动添加的两个类名分别对应两种不同的路由匹配模式:模糊匹配精确匹配

  • 匹配规则:只要当前浏览器地址栏的路径to 属性指定的路径开头,即可匹配成功并添加该类名。
  • 应用场景:适用于包含二级路由或嵌套路由的父级导航。例如,to="/discover" 可以匹配 /discover/discover/playlist/discover/toplist 等所有以 /discover 开头的路径。
  • 使用建议:在实际开发中,绝大多数导航高亮需求推荐使用模糊匹配,因为它能确保在子路由切换时,父级导航依然保持高亮状态。
  • 匹配规则:当前浏览器地址栏的路径必须与 to 属性指定的路径完全一致,才能匹配成功并添加该类名。
  • 应用场景:适用于不需要匹配子路由的独立导航项。例如,to="/discover" 仅能匹配 /discover,若路径变为 /discover/playlist,则不会添加该类名。
  • 使用建议:仅在特殊场景下(明确要求路径完全一致才高亮)使用。

匹配模式对比总结

类名 匹配模式 匹配条件(假设 to="/my" 适用场景
router-link-active 模糊匹配 匹配 /my/my/one/my/two 包含嵌套路由的父级导航(推荐)
router-link-exact-active 精确匹配 仅匹配 /my 独立页面导航,无子路由

router-link课程总结

  1. 核心组件router-link 是 Vue Router 提供的全局组件,用于实现声明式导航。
  2. 属性配置:使用 to 属性替代 href 属性指定路由路径,且无需添加 # 号。
  3. 双重功能
    • 路由跳转:实现页面路径的切换与组件的渲染。
    • 自动高亮:自动为激活状态的导航项添加 CSS 类名,免去手动操作 DOM 的繁琐。
  4. 类名区分
    • router-link-active 代表模糊匹配,适用于大多数包含层级的导航高亮场景。
    • router-link-exact-active 代表精确匹配,仅适用于路径完全一致的严格场景。

通过合理使用 router-link 及其自动高亮机制,可以大幅提升导航组件的开发效率与代码可维护性。

Vue Router 导航高亮类名自定义配置

在 Vue Router 中,router-link 组件在路由匹配成功时,会自动添加高亮类名。默认情况下,Vue Router 提供两种高亮类名机制:

  • 精确匹配类名(router-link-exact-active:要求配置的路由路径与浏览器地址栏中的路径完全相等时,才会添加该类名并触发高亮效果。
  • 模糊匹配类名(router-link-active:只要求配置的路由路径包含当前地址栏中的路径片段,即可添加该类名并触发高亮效果。在实际项目开发中,模糊匹配的使用频率通常高于精确匹配。

默认的高亮类名设计较长,其主要优势在于避免与开发者自定义的 CSS 类名发生冲突。然而,在某些开发场景下,过长的类名会导致代码冗余,开发者通常希望使用更简短、语义化的自定义类名。例如,希望将精确匹配类名简化为 exact-active,将模糊匹配类名简化为 active

自定义高亮类名的配置方法

Vue Router 官方提供了全局配置选项,允许开发者在路由实例化时自定义高亮类名。只需在 VueRouter 的配置对象中添加以下两个属性:

  • linkActiveClass:用于配置模糊匹配所对应的激活类名。
  • linkExactActiveClass:用于配置精确匹配所对应的激活类名。

代码演示与效果验证

在路由配置文件(如 router/index.js)中,修改 VueRouter 实例的配置项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)

const router = new VueRouter({
routes: [
// 路由配置规则
],
// 自定义模糊匹配高亮类名
linkActiveClass: 'active',
// 自定义精确匹配高亮类名
linkExactActiveClass: 'exact-active'
})

export default router

开发提示:在 VS Code 等现代代码编辑器中,无需死记硬背配置项的完整拼写。只需在配置对象中输入关键字 link,编辑器会自动代码提示 linkActiveClasslinkExactActiveClass 选项。

配置完成并保存刷新页面后,通过浏览器开发者工具检查 router-link 渲染出的 a 标签,可以发现其类名已变更为自定义的 activeexact-active

样式代码的同步修改

修改全局路由配置后,原有的默认高亮类名将不再生效。因此,必须同步修改 CSS 样式代码,将选择器更新为新的自定义类名。

修改前的样式代码

1
2
3
a.router-link-active {
color: red;
}

修改后的样式代码

1
2
3
a.active {
color: red;
}

更新样式选择器后,导航链接的高亮效果即可恢复正常。

Vue Router 导航高亮类名自定义配置总结

  1. 默认高亮类名较长,可通过 Vue Router 全局配置进行自定义修改。
  2. VueRouter 实例配置项中,使用 linkActiveClass 配置模糊匹配的类名。
  3. VueRouter 实例配置项中,使用 linkExactActiveClass 配置精确匹配的类名。
  4. 修改路由配置后,务必同步更新 CSS 样式选择器,以确保高亮效果正常显示。

声明式导航跳转传参

在 Vue Router 中,声明式导航通常指代 <router-link> 组件。在实际业务场景中,页面跳转时往往需要携带参数。例如,在首页点击不同的热门搜索词,跳转到搜索详情页时,需要将对应的搜索关键字传递过去,以便目标页面根据该关键字发送请求并渲染搜索结果。

Vue Router 提供了两种主要的声明式导航跳转传参方式:

  1. 查询参数传参(Query)
  2. 动态路由传参(Params)

查询参数传参 (Query)

查询参数传参的方式与传统的 URL 地址栏传参格式一致,通过在路径后追加问号(?)及键值对来传递数据。

语法说明

  • 跳转配置:在 <router-link>to 属性中,路径后使用 ?参数名=参数值 的格式。若需传递多个参数,使用 & 符号进行分隔,例如 ?key1=value1&key2=value2
  • 参数接收:在目标组件中,通过 $route.query.参数名 获取传递的值。

代码实现

配置导航链接:

1
2
3
4
5
<!-- 传递单个参数 -->
<router-link to="/search?words=Vue">Vue</router-link>

<!-- 传递多个参数 -->
<router-link to="/search?words=前端培训&type=course">前端培训</router-link>

参数接收

在目标组件(如 Search.vue)中接收参数时,需注意模板语法与 JavaScript 逻辑中 this 关键字的使用差异。

在 HTML 模板中接收(可省略 this):

1
2
3
4
5
<template>
<div>
<p>当前搜索关键字:{{ $route.query.words }}</p>
</div>
</template>

在 JavaScript 逻辑中接收(如 created 生命周期钩子,必须使用 this):

1
2
3
4
5
6
7
8
9
10
export default {
created() {
// 在 JS 中必须通过 this 访问 $route
const words = this.$route.query.words;
console.log('接收到的搜索关键字:', words);

// 基于接收到的参数发送网络请求
// this.fetchSearchResults(words);
}
}

动态路由传参 (Params)

动态路由传参通过将参数直接嵌入到 URL 路径中来实现,其 URL 结构更加简洁优雅。

语法说明

动态路由传参需要严格遵循三个步骤:配置路由规则、配置导航链接、接收参数。

  • 配置路由规则:在路由配置中,使用冒号(:)定义动态参数,例如 path: '/search/:words'。冒号不可省略,否则将被视为普通静态路径。
  • 跳转配置:在 <router-link>to 属性中,直接拼接参数值,例如 to="/search/Vue"
  • 参数接收:在目标组件中,通过 $route.params.参数名 获取传递的值。注意此处的参数名必须与路由规则中定义的变量名保持一致。

代码实现

步骤一:配置路由规则

1
2
3
4
5
6
7
8
9
const router = new VueRouter({
routes: [
{
// 使用 :words 定义动态路由参数
path: '/search/:words',
component: Search
}
]
})

步骤二:配置导航链接

1
2
3
<!-- 路径后直接跟参数值,无需问号与键名 -->
<router-link to="/search/Vue">Vue</router-link>
<router-link to="/search/前端培训">前端培训</router-link>

参数接收

在 HTML 模板中接收:

1
2
3
4
5
<template>
<div>
<p>当前搜索关键字:{{ $route.params.words }}</p>
</div>
</template>

在 JavaScript 逻辑中接收:

1
2
3
4
5
6
7
export default {
created() {
// 在 JS 中必须通过 this 访问 $route
const words = this.$route.params.words;
console.log('接收到的搜索关键字:', words);
}
}

两种传参方式的对比与选择

在实际开发中,应根据具体的业务场景选择合适的传参方式。

对比维度 查询参数传参 (Query) 动态路由传参 (Params)
URL 表现形式 /search?words=Vue /search/Vue
适用场景 适合传递多个参数,或参数为可选状态。 适合传递单个核心参数(如文章ID、用户ID)。
多参数处理 使用 & 分隔,如 ?a=1&b=2,扩展性强。 路径拼接较为繁琐,不推荐传递过多参数。
路由配置要求 无需修改基础路由规则,直接跳转即可。 必须提前在路由配置中声明动态参数(如 :id)。
代码简洁度 跳转链接需书写完整的键值对,相对冗长。 跳转链接直接拼接值,更加简洁优雅

选择建议

  • 当需要传递多个筛选条件、分页参数时,优先使用查询参数传参
  • 当仅传递单个标识符(如商品详情 ID),且希望 URL 更加美观、符合 RESTful 风格时,优先使用动态路由传参

动态路由参数的可选符

在默认情况下,若路由规则配置为 path: '/search/:words',则该路径强制要求必须携带参数。如果用户直接访问 /search(不携带任何参数),Vue Router 将无法匹配到该路由规则,导致页面显示空白。

解决方案:

若业务场景要求该参数为可选状态(即传参和不传参均能匹配到同一组件),可以在动态路由参数后添加可选符(问号 ?

修改路由配置:

1
2
3
4
5
6
7
8
9
const router = new VueRouter({
routes: [
{
// 在参数名 words 后添加 ?,使其成为可选参数
path: '/search/:words?',
component: Search
}
]
})

效果说明

  • 访问 /search/Vue:成功匹配,this.$route.params.words 的值为 "Vue"
  • 访问 /search:成功匹配,this.$route.params.words 的值为 undefined

通过在组件内部对 this.$route.params.words 进行判空处理,即可完美兼容带参跳转与无参直接访问的场景。

Vue Router 路由进阶配置

路由重定向(Redirect)

业务场景与需求分析

在单页面应用中,当用户首次打开网站时,通常访问的是根路径(/)。如果根路径没有匹配到任何组件,页面内容区域将显示为空白。为了提升用户体验,需要在访问根路径时,自动跳转到指定的首页路径(如 /home)。

核心概念

重定向是指当用户访问路径 A 时,通过路由配置强制将其跳转到路径 B。在 Vue Router 中,通过配置 redirect 属性即可实现该功能。

语法格式与代码示例

在路由配置数组(routes)中额外添加一条规则,使用 path 指定需要匹配的原始路径,使用 redirect 指定需要跳转的目标路径。

1
2
3
4
5
6
7
8
9
10
11
12
13
import Home from '@/views/Home.vue'
import Search from '@/views/Search.vue'

const router = new VueRouter({
routes: [
// 配置重定向规则:访问 '/' 时强制跳转到 '/home'
{ path: '/', redirect: '/home' },

// 正常路由规则
{ path: '/home', component: Home },
{ path: '/search', component: Search }
]
})

重点说明

  • pathredirect 的值可以根据实际业务需求进行修改。
  • 重定向规则在路由匹配时优先级较高,能够有效避免根路径下的页面空白问题。

路由 404 页面配置

业务场景与需求分析

当用户访问了项目中未配置的路径(例如 /list)时,由于没有匹配的组件,页面会显示空白。在规范的 Web 应用中,应当提供一个 404 提示页面(如 NotFound 组件),告知用户当前访问的页面不存在。

核心概念

在 Vue Router(Vue 2 对应的 Vue Router 3.x 版本)中,可以使用通配符 * 来匹配任意路径。当所有前置路由规则都未被命中时,通配符规则将被触发,从而渲染 404 提示组件。

语法格式与代码示例

首先创建 404 提示组件(如 NotFound.vue),然后在路由配置数组的最末尾添加通配符规则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import Home from '@/views/Home.vue'
import Search from '@/views/Search.vue'
import NotFound from '@/views/NotFound.vue'

const router = new VueRouter({
routes: [
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home },
{ path: '/search', component: Search },

// 404 路由规则:必须放置在路由数组的最后面
{ path: '*', component: NotFound }
]
})

重点说明

  • 位置要求:通配符 * 的规则必须配置在整个路由数组的最后面。因为 Vue Router 的路由匹配机制是从上往下依次进行的,如果将其放在前面,会导致后续的所有正常路由都被拦截。
  • 通配符 * 代表任意路径,专门用于处理未定义路由的兜底逻辑。

路由模式设置(Hash 与 History)

业务场景与需求分析

默认情况下,Vue Router 使用 Hash 模式,浏览器地址栏的 URL 中会带有一个 # 号(例如 http://example.com/#/home)。这种格式在视觉上不够自然,且不符合常规 Web 应用的 URL 规范。实际企业级项目中,通常希望使用不带 # 号的 History 模式(例如 http://example.com/home)。

核心概念与模式对比

Vue Router 提供了两种路由模式,其底层实现原理有所不同:

  • Hash 模式(默认)

    • URL 特征:带有 # 号。
    • 底层原理:基于 HTML 的锚点(a 标签)以及 onhashchange 事件实现。
    • 特点:兼容性较好,无需后端服务器进行额外配置,刷新页面不会向服务器发送真实路径请求。
  • History 模式

    • URL 特征:不带 # 号,路径更加美观、标准。
    • 底层原理:基于 HTML5 History API(pushStatereplaceState)实现。
    • 特点:URL 更加符合传统网页规范,但需要后端服务器配置访问规则以支持前端路由。

语法格式与代码示例

在创建路由实例时,通过 mode 属性进行模式切换。

1
2
3
4
5
6
7
8
9
10
const router = new VueRouter({
// 将路由模式切换为 History 模式
mode: 'history',
routes: [
{ path: '/', redirect: '/home' },
{ path: '/home', component: Home },
{ path: '/search', component: Search },
{ path: '*', component: NotFound }
]
})

注:如果不配置 mode 属性或配置为 mode: 'hash',则使用默认的 Hash 模式。

部署注意事项(重要)

  • 前端代码无感知:从 Hash 模式切换到 History 模式,前端代码中的路由跳转逻辑(如 router-linkthis.$router.push)无需做任何修改。
  • 后端服务器配置:一旦采用 History 模式,由于 URL 是真实的路径,当用户直接访问该路径或刷新页面时,浏览器会向服务器发送请求。如果服务器没有配置相应的重定向规则,将会返回 404 错误。
  • 解决方案:在项目上线部署时,必须提醒后端开发人员配置服务器规则(如 Nginx 的 try_files 配置),将所有未匹配到的静态资源请求重定向到前端的 index.html 文件,由前端路由接管后续渲染。

Vue Router 编程式导航与路由传参

编程式导航概述

在实际前端开发中,除了使用 <router-link> 标签进行声明式导航外,经常需要通过 JavaScript 代码触发路由跳转。例如:点击搜索按钮后跳转至搜索结果页,或登录成功后跳转至首页。在 Vue Router 中,这种通过 JavaScript 代码实现路由跳转的方式称为编程式导航

在传统的多页应用中,通常使用 location.href 进行页面跳转;但在 Vue 单页应用(SPA)中,由于路由切换本质上是组件的替换,必须使用 Vue Router 提供的实例方法来实现,其核心 API 为 this.$router.push()

路由跳转的两种基本方式

通过 path 路径跳转

通过路由配置中的 path 属性进行跳转,是最基础且常用的方式。只要路由规则中配置了对应的路径,即可直接进行跳转。

  • 简写语法:直接传入路径字符串。适用于无需传参的简单跳转。
    1
    this.$router.push('/search')
  • 完整对象语法:传入包含 path 属性的对象。
    1
    this.$router.push({ path: '/search' })

通过 name 命名路由跳转

通过路由配置中的 name 属性进行跳转。使用此方式的前提是,必须在路由规则中为目标路由配置 name 属性。

  • 路由配置前提
    1
    2
    3
    4
    5
    {
    path: '/search',
    name: 'Search',
    component: Search
    }
  • 跳转语法:传入包含 name 属性的对象。
    1
    this.$router.push({ name: 'Search' })
  • 适用场景:当路由路径层级较深或路径字符串较长时,使用命名路由跳转更为简洁,且后期修改路径时无需更改跳转代码。

路由跳转传参机制

在路由跳转时,通常需要携带参数(如用户在输入框中输入的搜索关键字)。Vue Router 支持两种传参方式:查询参数传参(Query)动态路由传参(Params)。无论是使用 path 还是 name 进行跳转,均支持这两种传参方案。

查询参数传参(Query)

查询参数会拼接在 URL 的末尾,以 ? 开头,多个参数以 & 分隔(例如:/search?keyword=vue)。

  • 结合 path 跳转
    • 字符串拼接法(适用于参数较少):
      1
      this.$router.push('/search?keyword=' + this.inputValue)
    • 对象配置法(适用于参数较多,推荐):
      1
      2
      3
      4
      5
      6
      this.$router.push({
      path: '/search',
      query: {
      keyword: this.inputValue
      }
      })
  • 结合 name 跳转
    1
    2
    3
    4
    5
    6
    this.$router.push({
    name: 'Search',
    query: {
    keyword: this.inputValue
    }
    })
  • 参数接收:在目标组件中,通过路由实例的 query 对象获取参数。
    1
    this.$route.query.keyword

动态路由传参(Params)

动态路由传参将参数作为 URL 路径的一部分(例如:/search/vue)。使用此方式前,必须修改路由配置,在路径中使用冒号 : 定义动态参数段。

  • 路由配置前提
    1
    2
    3
    4
    5
    {
    path: '/search/:keyword',
    name: 'Search',
    component: Search
    }
  • 结合 path 跳转
    由于 Vue Router 的机制,当使用 path 进行跳转时,params 属性会被忽略。因此,结合 path 使用时,只能通过字符串拼接的方式将参数直接写入路径中。
    1
    this.$router.push('/search/' + this.inputValue)
  • 结合 name 跳转(推荐用于 params 传参):
    1
    2
    3
    4
    5
    6
    this.$router.push({
    name: 'Search',
    params: {
    keyword: this.inputValue
    }
    })
  • 参数接收:在目标组件中,通过路由实例的 params 对象获取参数。
    1
    this.$route.params.keyword

传参方案选型与最佳实践

在实际项目开发中,应根据具体的业务场景选择合适的跳转与传参方案,以保证代码的可读性与可维护性。

跳转方式选择原则(path vs name)

  • 优先使用 path:若路由路径较短且结构简单,直接使用 path 路径跳转,代码语义更直观。
  • 优先使用 name:若路由路径较长、层级较深,或项目存在多语言、动态路由前缀等复杂场景,使用 name 命名路由跳转更为合适。

传参方式选择原则(query vs params)

  • 优先使用 query:若传递的参数较多,或参数为可选状态(如分页页码、筛选条件),推荐使用 query 查询参数传参。其 URL 表现清晰,支持对象化配置,且刷新页面不会丢失参数。
  • 优先使用 params:若传递的是单个核心标识参数(如文章 ID、商品 ID),且该参数是页面渲染的必要条件,推荐使用 params 动态路由传参。其 URL 更加简洁,符合 RESTful 架构风格。