Vue 路由 (vue-router) 详细总结

一、传统 web 应用与单页面 web 应用

1.1 传统 web 应用

传统 web 应用由多个 HTML 页面组成,页面切换时会重新加载整个页面,导致用户体验不够流畅,对服务器压力较大。

1.2 单页面 web 应用 (SPA)

单页面应用只有一个 HTML 页面,通过 JavaScript 动态更新页面内容,实现局部刷新,具有以下特点:

  • 用户体验好:响应性强,类似桌面应用的即时性。
  • 服务器压力小:服务器只需提供数据,不负责页面渲染。
  • 前后端分离:前端专注于界面和交互,后端提供 API,便于团队协作和代码维护。

但也存在一些缺点:

  • 首次加载耗时:需加载所有资源,初始加载时间较长。
  • SEO 不友好:搜索引擎不易爬取动态内容,影响搜索引擎优化。
  • 开发复杂度高:需管理页面状态和复杂交互,对开发者要求较高。

二、路由与路由器

2.1 路由 (route)

路由是 URL 路径与对应组件之间的映射关系,由路径 (key) 和组件 (value) 组成,用于确定访问特定 URL 时渲染的组件。

2.2 路由器 (router)

路由器用于管理多个路由,负责调度和管理应用中的所有路由规则,决定不同路径下显示的组件。

三、Vue 路由的使用

3.1 创建组件

使用 Vue 创建组件,如 app.vueMyHeader.vueMyFooter.vueHome.vue 等,通过 <template> 定义页面结构,<script> 导入和注册组件,<style> 设置样式。

3.2 安装 vue-router

根据 Vue 版本选择合适的 vue-router 版本,Vue 2 使用 vue-router@3,Vue 3 使用 vue-router@4,安装时若报错可加 --legacy-peer-deps 参数。

3.3 配置路由环境

main.js 中导入 Vue、App 等,创建 Vue 实例并注册路由器对象。在 src 目录下新建 router 文件夹,创建 index.js 配置路由器对象,导入 Vue、VueRouter,注册 VueRouter,导入路由组件,创建 VueRouter 实例并配置 routes(路由规则)。

3.4 使用路由

在组件中使用 <router-link> 配置路由关系,通过 to 属性指定路径,点击时跳转到对应路由组件。在 app.vue 中用 <router-view /> 指定路由组件显示位置。

四、多级路由

4.1 创建二级路由组件

创建二级路由组件,如 hot.vueagree.vuemore.vue

4.2 配置二级路由关系

router/index.js 中,于对应的一级路由 component 配置项下添加 children 数组,写入二级路由的 pathcomponent

4.3 使用二级路由

在二级路由组件中使用 <router-link> 时,路径要写完整。在二级路由组件中设置 <router-view /> 作为二级路由组件的显示位置。

五、路由命名

在路由关系中添加 name 配置,可简化 to 的编写,后期 params 传参也需用到 name,在使用时通过 name 简化 to 的写法。

六、路由参数传递

6.1 query 传参

配置详情页组件,在 router/index.js 中配置对应路由。传递参数时通过 :to 的对象形式,指定 namequery 参数。在详情页组件中通过 this.$route.query 拿取传递的参数并展示。

6.2 params 传参

新建 detail 组件并配置路由关系,若采用字符串形式拼接参数,需在路由 path 处进行参数占位;若采用对象形式传参,则可不占位。在传递参数的地方,通过 :to 的对象形式,指定 nameparams 参数。在 detail 组件中通过 this.$route.params 接收参数。

七、路由的 props

为了简化 query 和 params 参数的接收,让插值语法更简洁,在接收参数的组件路由中配置 props。有三种写法:

  • 对象写法:传固定值。
  • 函数写法:返回动态值。
  • 布尔值写法:将 params 数据转为 props,仅针对 params 传参。

八、router-link 的 replace 属性

浏览器历史记录存储在栈数据结构中,有 push 模式(默认,先进后出)和 replace 模式。开启 replace 模式可通过 <router-link :replace="true"><router-link replace>

九、编程式路由导航

不通过点击超链接切换路由,而是通过编写代码实现,叫编程式路由导航。相关 API 有:

  • this.$router.push():push 模式,可传对象(含 name、query 等)指定跳转路径。
  • this.$router.replace():replace 模式。
  • this.$router.forward():前进。
  • this.$router.back():后退。
  • this.$router.go(2):前进几步,负数则后退几步。

使用时注意重复执行 push 或 replace 的 API 会因返回 Promise 对象而报错,需在参数上添加两个回调函数。

十、缓存路由组件

默认路由切换时组件会被销毁,有时需缓存组件。用 <keep-alive include="组件名称"> 包裹 <router-view/>,不写 include 则缓存所有路由组件,指定多个缓存路由可用数组形式。被 <keep-alive> 包裹的路由组件有特有的生命周期函数 activated(被激活时触发)和 deactivated(失活时触发)。

十一、路由守卫

11.1 全局前置守卫

在创建 router 后、暴露 router 前书写,用 router.beforeEach((to, from, next)=>{...}),在切换任意组件前执行。callback 函数有 to(去哪里)、from(从哪来)、next(继续放行)三个参数。可在路由对象的 meta 中定义自定义属性,如鉴权属性。

11.2 全局后置守卫

在 router/index.js 文件中创建 router 对象后、暴露前书写,用 router.afterEach((to, from)=>{...}),在切换完任意路由后执行,通常用于切换路由时更换 title 标题栏。

11.3 局部路由守卫

  • path 守卫(路由守卫):写在 route 对象中的 beforeEnter(),进入对应路由组件前被调用。
  • component 守卫(组件守卫):写在路由组件的 xxx.vue 文件中,beforeRouteEnter 在进入路由组件前执行,beforeRouteLeave 在离开路由组件前执行。

十二、前端项目打包

xxx.vue 文件需用项目构建工具(如 webpack)打包编译成浏览器可识别的 html、css、js 文件。路由有 hash 模式和 history 模式两种路径模式:

  • hash 模式:路径带 #,兼容性好,上线刷新地址不会 404。
  • history 模式:路径美观,但上线后刷新地址可能 404,需后端配合解决。

默认是 hash 模式,开启 history 模式需在 router/index.js 中创建路由器对象时添加 mode 配置项。项目打包命令为 npm run build

十三、其他注意事项

在实际开发中,还需注意以下几点:

  1. 路由组件的组织:将路由组件与普通组件分开存放,路由组件放到 pages 或 views 目录,普通组件放到 components 目录下。
  2. 路由组件的生命周期:路由组件在切换时会被销毁,可通过 destroyed 生命周期钩子进行相关操作。
  3. 路由组件的属性:路由组件有两个重要属性,$route(属于自己的路由对象)和 $router(多组件共享的路由器对象)。
  4. 路由的 props 配置:为了简化参数接收,可使用 props 配置,让插值语法更加简洁。
  5. 路由的 replace 属性:根据需求选择合适的路由模式,避免不必要的历史记录堆积。
  6. 编程式路由导航的错误处理:在使用编程式路由导航时,注意处理重复执行 push 或 replace 的 API 可能导致的错误。
  7. 缓存路由组件的使用场景:根据实际需求合理使用缓存路由组件,避免不必要的内存占用。
  8. 路由守卫的合理应用:根据项目的权限控制和页面加载需求,合理使用全局前置守卫、全局后置守卫和局部路由守卫。
  9. 前端项目打包的配置:在项目打包前,确保配置正确,避免因配置问题导致打包后的项目无法正常运行。