一、传统 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.vue
、MyHeader.vue
、MyFooter.vue
、Home.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.vue
、agree.vue
、more.vue
。
4.2 配置二级路由关系
在 router/index.js
中,于对应的一级路由 component
配置项下添加 children
数组,写入二级路由的 path
和 component
。
4.3 使用二级路由
在二级路由组件中使用 <router-link>
时,路径要写完整。在二级路由组件中设置 <router-view />
作为二级路由组件的显示位置。
五、路由命名
在路由关系中添加 name
配置,可简化 to
的编写,后期 params
传参也需用到 name
,在使用时通过 name
简化 to
的写法。
六、路由参数传递
6.1 query 传参
配置详情页组件,在 router/index.js
中配置对应路由。传递参数时通过 :to
的对象形式,指定 name
和 query
参数。在详情页组件中通过 this.$route.query
拿取传递的参数并展示。
6.2 params 传参
新建 detail
组件并配置路由关系,若采用字符串形式拼接参数,需在路由 path
处进行参数占位;若采用对象形式传参,则可不占位。在传递参数的地方,通过 :to
的对象形式,指定 name
和 params
参数。在 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
。
十三、其他注意事项
在实际开发中,还需注意以下几点:
- 路由组件的组织:将路由组件与普通组件分开存放,路由组件放到 pages 或 views 目录,普通组件放到 components 目录下。
- 路由组件的生命周期:路由组件在切换时会被销毁,可通过
destroyed
生命周期钩子进行相关操作。 - 路由组件的属性:路由组件有两个重要属性,
$route
(属于自己的路由对象)和$router
(多组件共享的路由器对象)。 - 路由的 props 配置:为了简化参数接收,可使用 props 配置,让插值语法更加简洁。
- 路由的 replace 属性:根据需求选择合适的路由模式,避免不必要的历史记录堆积。
- 编程式路由导航的错误处理:在使用编程式路由导航时,注意处理重复执行 push 或 replace 的 API 可能导致的错误。
- 缓存路由组件的使用场景:根据实际需求合理使用缓存路由组件,避免不必要的内存占用。
- 路由守卫的合理应用:根据项目的权限控制和页面加载需求,合理使用全局前置守卫、全局后置守卫和局部路由守卫。
- 前端项目打包的配置:在项目打包前,确保配置正确,避免因配置问题导致打包后的项目无法正常运行。