Skip to content

S11-03 Vue-路由

[TOC]

前言

路由发展

  • 后端路由阶段
  • 前后端分离阶段
  • 单页面富应用(SPA)

后端路由阶段

服务器直接生产渲染好对应的HTML页面, 返回给客户端进行展示

一个页面有自己对应的网址, 也就是URL。URL会发送到服务器, 服务器会通过正则对该URL进行匹配, 并且最后交给一个Controller进行处理。Controller进行各种处理, 最终生成HTML或者数据, 返回给前端

优点:

  • 1、渲染好的页面, 不需要单独加载任何的js和css, 可以直接交给浏览器展示
  • 2、有利于SEO的优化

缺点:

  • 整个页面的模块由后端人员来编写和维护
  • 前端开发人员如果要开发页面, 需要通过PHP和Java等语言来编写页面代码
  • HTML代码和数据以及对应的逻辑会混在一起, 编写和维护困难

前后端分离阶段

后端只提供API来返回数据,前端通过Ajax获取数据,并且可以通过JavaScript将数据渲染到页面中

优点:

  • 前后端责任的清晰,后端专注于数据上,前端专注于交互和可视化
  • 当移动端(iOS/Android)出现后,后端不需要进行任何处理,依然使用之前的一套API

路由模式

  • URL的hash
  • HTML5的History

URL的hash

URL的hash也就是锚点(#), 本质上是改变window.location的href属性。我们可以通过直接赋值location.hash来改变href, 但是页面不发生刷新

优点:

  • 兼容性更好,在老版IE中都可以运行

缺点:

  • 有一个#,显得不像一个真实的路径

示例:

image-20221017224542819

HTML5的History

history接口是HTML5新增的, 它有六种模式改变URL而不刷新页面

  • history.replaceState:替换原来的路径
  • history.pushState:使用新的路径
  • history.popState:路径的回退
  • history.go:向前或向后改变路径
  • history.forward:向前改变路径
  • history.back:向后改变路径

示例:

image-20221018213218002

基础

vue-router概述

目前前端流行的三大框架, 都有自己的路由实现:Angular的ngRouter,React的ReactRouter,Vue的vue-router

vue-router是基于路由和组件的:

  • 路由用于设定访问路径, 将路径组件映射起来。
  • 在vue-router的单页面应用中, 页面的路径的改变就是组件的切换

安装

sh
# 安装4.x版本的vue-router
npm install vue-router@4

基本使用

步骤:

  • 1、创建路由组件
  • 2、配置路由映射: 组件和路径映射关系的routes数组
  • 3、创建路由对象:通过createRouter创建路由对象,并且传入routes和history模式
  • 4、使用路由:通过 <router-link><router-view>

示例:

  • router/index.js

image-20221018223950786

  • main.js

image-20221018224053237

  • app.vue

image-20221018224201544

属性:

  • to:String | Object。表示目标路由的链接。当被点击后,内部会立刻把 to 的值传到 router.push()
  • replace:Bolean,默认false。设置 replace 属性的话,当点击时,会调用 router.replace() 。导航后不会留下历史记录
  • active-class:String,默认router-link-active 。链接激活时,应用于渲染的 <a> 的 class。
  • exact-active-class:String,默认 router-link-exact-active 。链接精准激活时,应用于渲染的 <a> 的 class。
  • custom:Boolean,默认false<router-link> 是否应该将其内容包裹在 <a> 元素中
  • v-slot:{ href, route, navigate, isActive, isExactActive }。作用域插槽,暴露底层的定制能力

router-view

属性:

  • name:String。如果 <router-view> 设置了 name,叫命名视图。则会渲染对应的路由配置中 components 下的相应组件。
  • route:String。一个路由地址的所有组件都已被解析(如果所有组件都被懒加载),因此可以显示。
  • v-slot:{ Component, route } 。<router-view> 暴露了一个 v-slot API,主要使用 <transition><keep-alive> 组件来包裹你的路由组件。

router-link的v-slot

VueRouter4添加的用来替代3时期的 tag 属性,并且它更加灵活

使用:

  • 1、使用custom表示我们整个元素要自定义
  • 2、使用v-slot来作用域插槽来获取内部传给我们的值
    • href:解析后的 URL
    • route:解析后的规范化的route对象
    • navigate:触发导航的函数
    • isActive:是否匹配的状态
    • isExactActive:是否是精准匹配的状态

image-20221022215022934

router-view的v-slot

router-view也提供给我们一个插槽,可以用于 <transition><keep-alive> 组件来包裹你的路由组件

v-slot:

  • Component:要渲染的组件
  • route:解析出的标准化路由对象

使用:

image-20221022215319004

动画:

image-20221022215337879

路由默认路径

让路径默认跳到到首页, 并且渲染首页组件

image-20221022195658937

路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。

Vue Router 支持开箱即用的动态导入,这意味着你可以用动态导入代替静态导入:

image-20221022201426826

component可以传入一个组件,也可以接收一个函数,该函数需要返回一个Promise,而import函数就是返回一个Promise

组件按组分块

想把某个路由下的所有组件都打包在同个异步块 (chunk) 中。只需要使用命名 chunk,一个特殊的注释语法来提供 chunk name (需要 Webpack > 2.4):

image-20221022201951363

动态路由匹配

基本使用

很多时候,我们需要将给定匹配模式的路由映射到同一个组件。例如,我们可能有一个 User 组件,它应该对所有用户进行渲染,但用户 ID 不同。在 Vue Router 中,我们可以在路径中使用一个动态字段来实现,我们称之为 路径参数

route映射:

image-20221022203516572

组件:

image-20221022203557472

router-link:

image-20221022203658800

组件中获取路径参数

  • template: $route.params.id

  • options: this.$route.params.id

  • composition: useRoute().params.id

匹配多个参数

可以在同一个路由中设置有多个 路径参数,它们会映射到 $route.params 上的相应字段

image-20221022204308747

image-20221022204445721

匹配所有路由或Not found路由

常规参数只匹配 url 片段之间的字符,用 / 分隔。如果我们想匹配任意路径,我们可以使用自定义的 路径参数 正则表达式,在 路径参数 后面的括号中加入 正则表达式 :

image-20221022205126868

通过 $route.params.pathMatch 获取到传入的参数

在这个特定的场景中,我们在括号之间使用了自定义正则表达式,并将pathMatch 参数标记为可选可重复*。这样做是为了让我们在需要的时候,可以通过将 path 拆分成一个数组,直接导航到路由:

image-20221022205334295

嵌套路由

基本使用

路由映射:

image-20221022210647903

根组件:

image-20221022210713191

User组件:

image-20221022210818312

匹配到嵌套子路由

当你访问 /user/eduardo 时,在 Userrouter-view 里面什么都不会呈现,因为没有匹配到嵌套路由。也许你确实想在那里渲染一些东西。在这种情况下,你可以提供一个空的嵌套路径

image-20221022210944869

子路由命名

确保导航到 /user/:id始终显示嵌套子路由 UserHome

image-20221022211057926

父路由命名

导航到命名父路由不导航到嵌套子路由

注意: 重新加载页面将始终显示嵌套的子路由,因为它被视为指向路径/users/:id 的导航,而不是命名路由

image-20221022211249280

编程式导航

$router.push()

导航到不同的位置

在 Vue 实例中,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push

$router.push 会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,会回到之前的 URL。

当你点击 <router-link> 时,内部会调用这个方法

image-20221022211807565

注意:如果提供了 pathparams 会被忽略,上述例子中的 query 并不属于这种情况。

image-20221022212043836

由于属性 torouter.push 接受的对象种类相同,所以两者的规则完全相同。

router.push 和所有其他导航方法都会返回一个 Promise,让我们可以等到导航完成后才知道是成功还是失败。

$router.replace()

替换当前位置

它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,它取代了当前的条目。

image-20221022212349424

$router.go()

横跨历史

该方法采用一个整数作为参数,表示在历史堆栈中前进或后退多少步,类似于 window.history.go(n)

image-20221022212550028

动态添加路由

对路由的添加通常是通过 routes 选项来完成的,但是在某些情况下,你可能想在应用程序已经运行的时候添加路由

**应用场景:**根据用户不同的权限,注册不同的路由

语法:

js
// 动态添加一个【路由】
$router.addRoute(路由对象)

// 动态添加一个【子路由】
$router.addRoute('父路由name', 子路由对象)

示例:

动态添加一个【路由】

image-20221022215920723

动态添加一个【子路由】

image-20221022215940537

动态删除路由

三种删除方式:

  • 1、添加一个name相同的路由
  • 2、通过removeRoute方法,传入路由的名称
  • 3、通过addRoute方法的返回值回调

示例:

1、添加一个name相同的路由

image-20221022220128117

2、通过removeRoute方法,传入路由的名称

image-20221022220204984

3、通过addRoute方法的返回值回调

image-20221022220234445

路由导航守卫

$router.beforeEach: 全局前置守卫

语法:

image-20221022220507349

参数:

  • to:即将要进入的路由目标对象
  • from:当前导航正要离开的路由对象
  • next:在Vue2中我们是通过next函数来决定如何进行跳转的【Vue3不再推荐】

返回值:

  • false:取消当前导航
  • undefined | 不返回:进行默认导航
  • 一个路由地址:String | Object。跳转到该路由地址

注意:Vue3中利用返回值取代了Vue2中next的作用

示例:

image-20221022221134926

RouteRecord

  • path
  • component
  • name: 路由记录独一无二的名称
  • redirect
  • children
  • alias
  • beforeEnter
  • props
  • sensitive
  • strict
  • meta: 自定义的数据

$route

  • $route.path
  • $route.fullPath
  • $route.params
  • $route.query
  • $route.hash
  • $route.matched
  • $route.name
  • $route.meta
bash
**1.$route.path**
      字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"。
**2.$route.params**
      一个 key/value 对象,包含了 动态片段 全匹配片段,
      如果没有路由参数,就是一个空对象。
**3.$route.query**
      一个 key/value 对象,表示 URL 查询参数。
      例如,对于路径 /foo?user=1,则有 $route.query.user == 1,
      如果没有查询参数,则是个空对象。
**4.$route.hash**
      当前路由的 hash (不带 #) ,如果没有 hash 值,则为空字符串。锚点
**5.$route.fullPath**
      完成解析后的 URL,包含查询参数和 hash 的完整路径。
**6.$route.matched**
      数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
**7.$route.name    当前路径名字**
**8.$route.meta  路由元信息

$router

  • 属性
  • $router.currentRoute
  • $router.options
  • 动态添加、删除路由
  • $router.addRoute()
  • $router.removeRoute()
  • $router.resolve()
  • $router.hasRoute()
  • $router.getRoutes()
  • 导航守卫
  • $router.beforeEach()
  • $router.beforeResolve()
  • $router.afterEach()
  • 编程式导航
  • $router.push()
  • $router.replace()
  • $router.back()
  • $router.forward()
  • $router.go()
  • $router.isReady()
  • $router.onError()