Angular复习笔记7-路由(下)
Angular复习笔记7-路由(下)
这是angular路由的第二篇,也是最后一篇。继续上一章的内容
路由跳转
Web应用中的页面跳转,指的是应用响应某个事件,从一个页面跳转到另一个页面的行为。对于使用Angular构建的单页应用而言,页面跳转实质上就是从一个配置项跳转到另一个配置项的行为。页面跳转流程如下图所示,当某个事件引发了跳转时,Angular会根据跳转时的参数生成一个UrlTree实例来和配置项进行匹配,如果匹配成功,则显示相应的组件并将新URL更新在浏览器地址栏中;如果匹配不成功,则报错。本节将对Angular应用中进行页面跳转的两种方式进行介绍。

使用指令进行跳转
指令跳转通过使用RouterLink指令来完成。该指令接收一个链接参数数组,Angular将根据该数组来生成UrlTree实例进行跳转。

如果不借助于RouterLink指令而以纯HTML的方式来定义超链接,所导致的结果是单击超链接后会使得整个页面被重新加载。

RouteLink的一个强大之处在于可以用在任何的HTML元素上。使得页面跳转不需要超链接。
此外,当RouterLink被激活时,还可以通过RouterLinkActive指令为其相应的HTML元素指定CSS类。下面的例子定义了一个CSS类.active,并通过routerLinkActive将其赋给收藏页的链接。当单击该链接后,.active类将被应用到<a>标签上。示例代码如下:

RouterLinkActive指令除可以作用于routerLink所在的元素之外,还可以作用于这些元素的任意祖先元素。当该祖先元素下的任意routerLink处于激活状态时,该祖先元素都将获得routerLinkActive指定的CSS类。下面的例子不管当前是处于联系人列表页还是收藏页,<nav>标签都将获得.active类。示例代码如下:

使用代码跳转
RouterLink仅仅相应click事件,如果需要其他形式的跳转,在可以使用Router对象的Router.navigateByUrl()或其兄弟方法Router.navigate()来完成。下面的例子实现了在进入联系人列表页1秒后自动跳转到收藏页的功能。示例代码如下:

Router.navigateByUrl()和Router.navigate()的不同之处在于传入的参数不同,前者需要传入一个表示url的字符串或UrlTree类型的参数,后者和RouterLink指令一样,需要一个链接参数数组。
这两个方法除可以通过第一个参数来指定目标配置项外,还支持用extras参数定义跳转的具体行为。例如,如果想在不改变URL的情况下完成跳转,则可以通过以下代码来完成:

关于extras参数的其他用法,感兴趣的读者可以参考官方文档来了解更多的内容,在此不再赘述。
路由参数
在“组件”章节中介绍了如何使用@Input装饰器向组件传递数据,除此之外,Angular路由还提供了路由参数的功能,允许通过URL向组件传递数据。
path参数
顾名思义,Path参数是通过解析URL的path部分来获取参数的。在定义一个配置项的path属性时,可以使用“/”字符来对path属性进行分段,如果一个分段以“:”字符开头,则URL中与该分段进行匹配的部分将作为参数传递到组件中。下面的代码为联系人详情页的路由配置项,其定义了一个名为id的Path参数,对于http://localhost:3000/detail/1,参数id的值为1;对于http://localhost:3000/detail/2,参数id的值则为2;依此类推。
本例中path的分段数是2,只有URL解析出来的分段数和path的分段数一致时,才能得到匹配。
给路由参数赋值,除可以直接在浏览器地址栏中输入URL外,还可以通过RouterLink指令或者跳转方法来完成:

在组件中获取Path参数,需要导入ActivatedRoute服务,该服务提供了两种方式,分别适用于不同页面间跳转和同一页面内跳转。
Angular应用从一个页面跳转到另一个新的页面,实质上是从一个配置项跳转到另一个配置项。在这个过程中,Angular除会为配置项所对应的组件创建实例外,还会为该配置项本身创建一个ActivatedRoute实例来表示该配置项已被激活。该ActivatedRoute实例包含了一个快照(即snapshot属性),记录了从当前URL中解析出来的所有Path参数。下面展示了通讯录例子中的DetailComponent组件是如何通过快照来获取Path参数的。示例代码如下:

此时通过http://localhost:3000/detail/1直接访问联系人详情页,可以在浏览器控制台上看到如下输出,则表示通过快照获取到的值是正确的。
创建DetailComponent组件实例
参数id的值为:1
但是当Angular在处理同一页面内跳转时,不会重新创建组件的实例,所以组件的构造函数和ngOnInit()方法都没有被调用到。为了解决这个问题,ActivatedRoute服务提供了一个Observable对象,允许对参数的更新进行订阅。示例代码如下:

Query参数
我们也可以通过解析URL的query部分来获取参数值。由于URL的query部分不用于和配置项进行匹配,因此每一个配置项都可以拥有任意多个查询参数。下面的URL给联系人列表页定义了一个查询参数,表示只希望在页面上显示5位联系人。
http://localhost:3000/list?limit=5
与Path参数类似,Query参数同样可以通过RouterLink指令或者跳转方法来赋值。示例代码如下:

Query参数的获取,需要借助于ActivatedRoute服务提供的Observable类型对象queryParams来完成。下面的代码片段展示了如何使用这个对象。

Matrix参数
页面上所有组件都可以访问Query参数的内容,如果想精准地向某一个组件传递参数,则需要使用Matrix参数。
Angular提供了Matrix参数,它通过在链接参数数组中插入一个对象来进行赋值。示例代码如下:
Angular会将该对象的属性转化为以“;”为分隔符的键值对,拼接到与该对象左边最近的URL分段上。依据上述链接参数数组生成的URL如下,DetailComponent组件和AlbumComponent组件都将获得不同的参数值:http://localhost:3000/detail/6;after=2015-01-01;before=2015-12-31/album;after=2016-01-01;before=2016-12-31
这种在一个URL分段内使用“;”分隔键值对的方式称为MatrixURI,由互联网之父TimBerners-Lee于1996年提出。根据其定义,每一个URL分段都可以拥有任意多个键值对,每个键值对只为其所在的分段服务。虽然MatrixURI一直没有进入HTML标准,但它能够清晰地表示出每一个URL分段所具有的键值对。Angular利用这个特性,将Matrix参数精准地传递给分段所对应的组件。Matrix参数的获取方式和Path参数一样,可以通过ActivatedRoute服务提供的快照和Observable对象两种方式来获取,在此不再赘述。
路由拦截
Angular的路由拦截允许在从一个配置项跳转到另一个配置项之前执行指定的逻辑,并根据执行的结果来决定是否进行跳转。Angular提供了五类路由拦截:
- CanActivate,激活拦截。
- CanActivateChild,与CanActivate类似,用于控制是否允许激活子路由配置项。
- CanDeactivate,反激活拦截。
- Resolve,数据预加载拦截。
- CanLoad,模块加载拦截。
关于路由拦截的内容会新开一个专题篇来讲述这个功能的方方面面,这里先不赘述。
模块的延迟加载
前文提到,Angular应用由一个根模块和任意多个特性模块组成。一个大型Web应用通常会包含为数不少的特性模块,如果在首屏加载时便将所有的特性模块加载进来,对于用户体验和服务器负载均会有所影响。为此,Angular路由提供了对特性模块进行延迟加载的支持,使得只有在真正需要某一个模块的时候,才将其加载进来。
与根模块需要初始化各项路由服务不同,特性模块仅需要对其路由配置进行解析,因此子路由模块通过调用RouterModule.forChild()方法来创建。示例代码如下:


最后,还需要对根模块的路由配置进行修改:

loadChildren指定了延迟加载模块的路径,井号“#”后面的表示模块类名。当用户访问地址/operate时,Angular才会加载operate.module.ts这个模块。
模块预加载
延迟加载使得首屏加载的资源包的大小减小很多,这些模块只在用户触发的时候才开始加载。但对于某些模块来说,触发时才加载可能不是最优的解决方案。这样的模块虽然不需要首屏加载,但可能有很大的概率用户会访问使用到,因此最好不用等待用户触发,而是在首屏资源加载完后立即加载,这种加载模式就叫作预加载。预加载的模块首先得是一个延迟加载的模块,让所有延迟加载的模块加上预加载功能非常简单,只需在根模块的RouterModule中添加一个preloadingStrategy配置项即可。示例代码如下:

加上这个配置后,所有的延迟加载模块将不再等待用户触发,而是等待首屏资源加载完后立即加载。不过,这样的配置显然不够灵活,更好的方式是对预加载的策略做自定义配置。开发者可以通过实现Angular提供的PreloadingStrategy接口自定义预加载策略。首先定义一个服务,并实现PreloadingStrategy接口。示例代码如下:

preload()方法的返回类型必须是一个Observable对象,Angular会遍历每一个route对象并执行preload()函数,以此来判断该route对应的模块是否需要进行预加载。它接受两个参数:
route:当前处理中的route对象。
load:内置异步模块加载器函数。上面这个例子直接返回Observable.of(null),表示不进行预加载。
MyPreloadingStrategy这个服务的目的是进行有选择的预加载,可以根据route对象里的data属性提供的信息进行判断。示例代码如下:

如果data对象里设置了preload为true,preload函数即返回load()加载器函数,这表示该路由对应的模块需要进行预加载。这个MyPreloadingStrategy服务已经完成了,下面需要把原来的PreloadAllModules替换成新的MyPreloadingStrategy。示例代码如下:

然后依据这个规则,控制模块预加载就变得非常简单了。在需要预加载的延迟加载路由配置项里进行配置:

在这个route对象里设置preload为true后,OperateModule的加载方式由原来的延迟加载变更为预加载,而其他延迟加载模块并不会受到影响,还是会等待用户触发时才加载。
Angular复习笔记7-路由(下)的更多相关文章
- Angular复习笔记7-路由(上)
Angular复习笔记7-路由(上) 关于Angular路由的部分将分为上下两篇来介绍.这是第一篇. 概述 路由所要解决的核心问题是通过建立URL和页面的对应关系,使得不同的页面可以用不同的URL来表 ...
- Angular复习笔记6-依赖注入
Angular复习笔记6-依赖注入 依赖注入(DependencyInjection)是Angular实现重要功能的一种设计模式.一个大型应用的开发通常会涉及很多组件和服务,这些组件和服务之间有着错综 ...
- angular复习笔记4-模板
Angular复习笔记4-模板 简介 模板是一种自定义的标准化页面,通过模板和模板中的数据结合,可以生成各种各样的网页.在Angular中,模板的默认语言是HTML,几乎所有的HTML语法在模板中都是 ...
- Angular复习笔记5-指令
Angular复习笔记5-指令 在Angular中,指令是一个重要的概念,它作用在特定的DOM元素上,可以扩展这个元素的功能,为元素增加新的行为.本质上,组件可以被理解为一种带有视图的指令.组件继承自 ...
- angular学习笔记(十七)-路由和切换视图
本篇介绍angular中如何通过判断url的hash值来显示不同的视图模板,并使用不同的控制器: 下面,通过一个例子,来一步一步说明它的用法: 我们要做一个邮箱应用,打开的时候显示的是邮件列表: 然后 ...
- angular复习笔记1-开篇
前言 学习和使用angular已经有一段时间了.这段时间利用angular做了一个系统,算是对angular有了一个全面的认识,趁着现在有一些时间,把angular的一些知识记录一下. 安装angul ...
- Angular 学习笔记 (路由外传 - RouteReuseStrategy)
refer : https://github.com/angular/angular/issues/10929 https://stackoverflow.com/questions/41280471 ...
- angular复习笔记3-组件
组件Component 组件是构成angular应用的核心,angular的有序运行依赖于组件的协同工作,组件之于angular应用就像是汽车和汽车零部件的意思. 概述 近几年的前端发展迅速,各种工程 ...
- angular复习笔记2-架构总览
angular架构总览 一个完整的Angular应用主要由6个重要部分构成,分别是:组件.模板.指令.服务.依赖注入和路由.这些组成部分各司其职,而又紧密协作,它们的关系如图所示. 与用户直接交互的是 ...
随机推荐
- Flask拾遗总汇1
目录 1.flask的路由分发方式 2.请求响应相关 3.flask配置文件拾遗(config) 4.路由系统参数配置 4.1 可传入参数: 4.2 常用路由系统有以上五 5.反向生成URL: url ...
- HDP 3.1.0 集成 Sqoop2 踩坑问题记录
HDP 3.1.0 集成 Sqoop2 踩坑问题记录 本文原始地址:https://sitoi.cn/posts/65261.html 问题一 $ sqoop:000> start job -n ...
- Shiro RememberMe 1.2.4 反序列化漏洞详细复现
0x00 前言 今天上班的时候收到了一个复测的任务,打开一看,shiro反序列化漏洞,What?这是个什么东西,经百度查找后才知道,原来是Java的开发框架,好吧,还是没听说过..由于初测报告上的过程 ...
- 神经网络中Batch Size的理解
直观的理解:Batch Size定义:一次训练所选取的样本数.Batch Size的大小影响模型的优化程度和速度.同时其直接影响到GPU内存的使用情况,假如你GPU内存不大,该数值最好设置小一点. 为 ...
- Amoeba读写分离(MySQL)
实验操作环境: centos服务器 三台机器 role: 192.168.189.129 master-主 192.168.189.130 master-从 192.168.189.131 ...
- [RN] React Native 获取地理位置
React Native 获取地理位置 实现原理: 1.用 navigator.geolocation.getCurrentPosition 获取到坐标信息 2.调用 高德地图 接口,解析位置数据 ...
- 网络协议 5 - ICMP 与 Ping
日常开发中,我们经常会碰到查询网络是否畅通以及域名对应 IP 地址等小需求,这时候用的最多的应该就是 ping 命令了. 那你知道 ping 命令是怎么工作的吗?今天,我们就来一起认识下 ping 命 ...
- priority_queue(优先队列)使用方法
priority_queue默认是一个大根堆: 并且出队方式与普通队列queue的front不一样,是top . 如果想用小根堆,可以修改定义时的参数: priority_queue<int,v ...
- GOOD BYE OI
大米饼正式退役了,OI给我带来很多东西 我会的数学知识基本都在下面了 博客园的评论区问题如果我看到了应该是会尽力回答的... 这也是我作为一个OIer最后一次讲课的讲稿 20190731 多项式乘法 ...
- 【字符串】KMP
Algorithm Task 给定一个文本串 \(S\) 和一个模式串 \(T\),求 \(T\) 在 \(S\) 中出现的所有位置. Limitations 要求时空复杂度均为线性. Solutio ...