4 vue-router路由

vue-router安装

在HbuilderX的项目管理器项目目录上,右键执行“使用命令行窗口打开所在目录”,在终端里输入:

官网的命令,默认时安装Vue-router4的版本,会报错。npm install vue-router@4

安装完毕后,在node_modules文件夹里会有一个vue-router文件夹。index.js里export导出了

命名路由

  有时,通过一个名称来标识一个路由显得更方便,特别是在链接一个路由,或者是执行一些跳转时。可以在创建Router实例时,在routes配置中给某个路由设置名称

  要链接到一个命名路由,可以给 router-linkto 属性传一个对象:

  这跟代码调用 router.push() 是一回事

  这两种方式都会把路由导航到 /user/123 路径

  命名路由的常见用途是替换router-link中的to属性,如果不使用命名路由,由router-link中的to属性需要设置全路径,不够灵活,且修改时较麻烦。使用命名路由,只需要使用包含name属性的对象即可

  [注意]如果设置了默认子路由,则不要在父级路由上设置name属性

声明式导航与编程式导航

  除了使用<router-link>创建a标签来定义导航链接,还可以借助router的实例方法,通过编写代码来实现

router.push(location)

应用场景:需要用js来控制跳转,比如用户登录后,跳转到首页。

  想要导航到不同的 URL,则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录,所以,当用户点击浏览器后退按钮时,则回到之前的 URL。

  1. https://www.bilibili.com/video/BV1qu411r7WT?spm_id_from=333.851.b_7265636f6d6d656e64.1
  2. https://www.bilibili.com/video/BV1BL411c78t/?spm_id_from=333.788.recommend_more_video.-1
  3. https://www.bilibili.com/video/BV1oz4y1U7fS/?spm_id_from=333.788.recommend_more_video.1

history

  当点击 <router-link> 时,这个方法会在内部调用,所以说,点击 <router-link :to="..."> 等同于调用 router.push(...)

  

在@click中,用$router表示路由对象,在methods方法中,用this.$router表示路由对象

  该方法的参数可以是一个字符串路径,或者一个描述地址的对象。例如:

router.replace(location)

  跟 router.push 很像,唯一的不同就是,它不会向 history 添加新记录,而是跟它的方法名一样 —— 替换掉当前的 history 记录

router.go(n)

  这个方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)

router.back()

组件引入的箭头函数写法

routes中组件定义方式:

  1. 使用import 把组件导入,然后component值为导入的名。

  2. 直接设置在component的值为一个匿名(箭头)函数

根路径

  设置根路径,需要将path设置为'/'

 

404页面

 

路由高亮

高亮即选中状态,给路由添加高亮的类。

1 全局配置

new VueRouter实例化时,添加linkActiveClass属性,也可不填,默认名为router-link-active,在全局样式里填写

linkActiveClass

  • 类型: string

  • 默认值: "router-link-active"

    全局配置 <router-link> 默认的激活的 class。

 

2 单独配置

利用:router-link的属性 active-class

active-class

  • 类型: string
  • 默认值: "router-link-active"

  

特殊情况

由于默认使用的是全包含匹配,即'/about'、也可以匹配到'/',如果需要精确匹配,仅仅匹配'/',则需要在router-link中设置exact属性

导入CSS文件

使用@import url方式

类名冲突的解决

在style标签上 添加 scoped 属性,使当前样式只会在该vue页面中生效。

 

导入js文件

使用 export导出 import导入。 @表示src的根目录

 

router路由分离

  1. src目录下建立router文件夹 router文件夹里新建index.js文件
  2. index.js 引入vue、vue-router、使用、配置路由规则、实例化vue-router
  3. 导出实例化对象
  4. 在main.js里引入

 

路由课堂练习

router-link练习

pages:

首页 index 关于我们 about 新闻中心 news 公司产品 product 联系我们 contact

comonents:

头部 header 底部 footer

 

this.$router.push 练习

pages:

首页 index 登录页 login

路由原理图

img

 

页面跳转传参

回顾

html 页面之间如何传参? =》url?key=val&key=val ?query=唐山港&hdq=sogou-wsse-b58ac8403eb9cf17-0003

路由传参

两种方式:

  1. query 传参(查询字符串)。 适用场景:页面搜索 https://juejin.cn/search?query=vue
  2. params 传参。 适用场景:详情页 https://juejin.cn/post/6977259197566517284

方法跳转

案例练习

思路:

新闻网站 开发者头条

页面结构 首页->列表页->详情页

组件:顶部组件 导航组件 边栏组件

数据源:

Api列表 - MXNZP.COM 穆仙念,人到中年

app_id:nkz2cwitngkms0hu

app_secret:Mmh0UVRKWEFUUGFiR0lEeVJqTkM2dz09

源码下载地址:

https://vkceyugu.cdn.bspapp.com/VKCEYUGU-dd9aa05c-e357-4d7c-8d53-2c40c0818169/25a9ce11-9eaa-487b-8220-4e1ef7724ba2.zip

运行前,先npm install

Axios:

  1. 安装

  2. 将axios挂在vue原型链上

  3. 使用

  4. axios 分离 config.js

     

  5. axios 拦截器

     

  6. axios方法、全局配置

     

路由作业

中国城市查询APP

要求:

  1. 首页:

    1. 通过接口,展示全国一级城市。点击某省,进入省级内容页。
    2. 首页要有搜索功能,输入省名,进行搜索,在省级页显示。
  2. 省级页:通过接口,展示该省下的所有市级城市。点击某市,进入市级内容页。

  3. 市级页:通过接口,展示该市下的所有县区级城市。

  4. 所有页面要有标题(以组件形式)。省、市页面要有返回上一页的按钮

 

重定向和别名

【重定向】

重定向通过 routes 配置来完成,下面例子是从 /a 重定向到 /b

  重定向的目标也可以是一个命名的路由:

  甚至是一个方法,动态返回重定向目标:

对于不识别的URL地址来说,常常使用重定向功能,将页面定向到首页显示

 

【别名】

重定向是指,当用户访问 /a时,URL 将会被替换成 /b,然后匹配路由为 /b,那么别名是什么呢?/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样

上面对应的路由配置为

『别名』的功能可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构

处理首页访问时,常常将index设置为别名,比如将'/home'的别名设置为'/index'。但是,要注意的是,的样式在URL为/index时并不会显示。因为,router-link只识别出了home,而无法识别index

嵌套路由

实际生活中的应用界面,通常由多层嵌套的组件组合而成。同样地,URL中各段动态路径也按某种结构对应嵌套的各层组件

  借助 vue-router,使用嵌套路由配置,就可以很简单地表达这种关系

要特别注意的是,router的构造配置中,children属性里的path属性只设置为当前路径,不要加斜杠,因为其会依据层级关系;而在router-link的to属性则需要设置为完全路径

如果要设置默认子路由,即点击foo时,自动触发foo1,则需要进行如下修改。将router配置对象中children属性的path属性设置为'',并将对应的router-link的to属性设置为'/foo'

 

命名视图

有时候想同时(同级)展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar(侧导航) 和 main(主内容) 两个视图,这个时候命名视图就派上用场了。可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default

一个视图使用一个组件渲染,因此对于同个路由,多个视图就需要多个组件。确保正确使用components配置

  下面是一个实例

 

动态路径

经常需要把某种模式匹配到的所有路由,全都映射到同个组件。例如,有一个 User 组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,可以在 vue-router 的路由路径中使用动态路径参数(dynamic segment)来达到这个效果

现在,像 /user/foo/user/bar 都将映射到相同的路由

下面是一个比较完整的实例,path:'/user/:id?'表示有没有子路径都可以匹配

一个路径参数使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。于是,可以更新 User 的模板,输出当前用户的 ID:

下面是一个实例

可以在一个路由中设置多段『路径参数』,对应的值都会设置到 $route.params 中。例如:

  除了 $route.params 外,$route 对象还提供了其它有用的信息,例如,$route.query(如果 URL 中有查询参数)、$route.hash 等等

【响应路由参数的变化】

使用路由参数时,例如从 /user/foo 导航到 user/bar原来的组件实例会被复用。因为两个路由都渲染同个组件,比起销毁再创建,复用则显得更加高效。不过,这也意味着组件的生命周期钩子不会再被调用

复用组件时,想对路由参数的变化作出响应的话,可以简单地 watch(监测变化) $route 对象:

[注意]有时同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:谁先定义的,谁的优先级就最高

  下面是一个实例

 

查询字符串

this.$route.params

实现子路由,除了使用动态参数,也可以使用查询字符串

 

 

  当需要设置默认查询字符串时,进行如下设置

过渡动效

<router-view> 是基本的动态组件,所以可以用 <transition> 组件给它添加一些过渡效果:

  下面是一个实例

 

【单个路由过渡】

上面的用法会给所有路由设置一样的过渡效果,如果想让每个路由组件有各自的过渡效果,可以在各路由组件内使用 <transition> 并设置不同的 name

路由元信息

 

定义路由的时候可以配置 meta 字段:

routes配置中的每个路由对象被称为路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,它可能匹配多个路由记录。例如,根据上面的路由配置,/foo/bar 这个URL将会匹配父路由记录以及子路由记录

一个路由匹配到的所有路由记录会暴露为 $route 对象(还有在导航钩子中的 route 对象)的 $route.matched 数组。因此,需要遍历 $route.matched 来检查路由记录中的 meta 字段

  下面例子展示在全局导航钩子中检查 meta 字段:

复制代码

【基于路由的动态过渡】

  可以基于当前路由与目标路由的变化关系,动态设置过渡效果。通过使用路由元信息,在每个路由对象上设置一个index属性保存其索引值

复制代码

复制代码

复制代码

复制代码

复制代码

 

 

导航钩子 (重点)

vue-router 提供的导航钩子主要用来拦截导航,让它完成跳转或取消。有多种方式可以在路由导航发生时执行钩子:全局的、单个路由独享的或者组件级的

【全局钩子】

可以使用 router.beforeEach 注册一个全局的 before 钩子

当一个导航触发时,全局的 before 钩子按照创建顺序调用。钩子是异步解析执行,此时导航在所有钩子 resolve 完之前一直处于 等待中

每个钩子方法接收三个参数:

下面是next()函数传递不同参数的情况

  • next(): 进行管道中的下一个钩子。如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
  • next(false): 中断当前的导航。如果浏览器的 URL 改变了(可能是用户手动或者浏览器后退按钮),那么 URL 地址会重置到 from 路由对应的地址。
  • next('/') 或者 next({ path: '/' }): 跳转到一个不同的地址。当前的导航被中断,然后进行一个新的导航。

[注意]确保要调用 next 方法,否则钩子就不会被 resolved。

同样可以注册一个全局的 after 钩子,不过它不像 before 钩子那样,after 钩子没有 next 方法,不能改变导航:

  下面是一个实例

复制代码

 

【单个路由独享】

  可以在路由配置上直接定义 beforeEnter 钩子

复制代码

这些钩子与全局 before 钩子的方法参数是一样的

【组件内钩子】

可以在路由组件内直接定义以下路由导航钩子

 

beforeRouteEnter钩子不能访问this,因为钩子在导航确认前被调用,因此即将登场的新组件还没被创建。

不过,可以通过传一个回调给 next来访问组件实例。在导航被确认的时候执行回调,并且把组件实例作为回调方法的参数

  可以在 beforeRouteLeave 中直接访问 this。这个 leave 钩子通常用来禁止用户在还未保存修改前突然离开。可以通过 next(false) 来取消导航

数据获取

 

有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,需要从服务器获取用户的数据。可以通过两种方式来实现:

1、导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示『加载中』之类的指示

2、导航完成之前获取:导航完成前,在路由的 enter 钩子中获取数据,在数据获取成功后执行导航。

从技术角度讲,两种方式都不错 —— 就看想要的用户体验是哪种

【导航完成后获取】

当使用这种方式时,会马上导航和渲染组件,然后在组件的 created 钩子中获取数据。有机会在数据获取期间展示一个 loading 状态,还可以在不同视图间展示不同的 loading 状态。

假设有一个 Post 组件,需要基于 $route.params.id 获取文章数据:

【导航完成前获取数据】

  通过这种方式,在导航转入新的路由前获取数据。可以在接下来的组件的 beforeRouteEnter 钩子中获取数据,当数据获取成功后只调用 next 方法

在为后面的视图获取数据时,用户会停留在当前的界面,因此建议在数据获取期间,显示一些进度条或者别的指示。如果数据获取失败,同样有必要展示一些全局的错误提醒