这是angular路由的第二篇,也是最后一篇。继续上一章的内容数组
Web应用中的页面跳转,指的是应用响应某个事件,从一个页面跳转到另外一个页面的行为。对于使用Angular构建的单页应用而言,页面跳转实质上就是从一个配置项跳转到另外一个配置项的行为。页面跳转流程以下图所示,当某个事件引起了跳转时,Angular会根据跳转时的参数生成一个UrlTree实例来和配置项进行匹配,若是匹配成功,则显示相应的组件并将新URL更新在浏览器地址栏中;若是匹配不成功,则报错。本节将对Angular应用中进行页面跳转的两种方式进行介绍。浏览器
指令跳转经过使用RouterLink指令来完成。该指令接收一个连接参数数组,Angular将根据该数组来生成UrlTree实例进行跳转。服务器
若是不借助于RouterLink指令而以纯HTML的方式来定义超连接,所致使的结果是单击超连接后会使得整个页面被从新加载。异步
RouteLink的一个强大之处在于能够用在任何的HTML元素上。使得页面跳转不须要超连接。函数
此外,当RouterLink被激活时,还能够经过RouterLinkActive指令为其相应的HTML元素指定CSS类。下面的例子定义了一个CSS类.active,并经过routerLinkActive将其赋给收藏页的连接。当单击该连接后,.active类将被应用到<a>标签上。示例代码以下:url
RouterLinkActive指令除能够做用于routerLink所在的元素以外,还能够做用于这些元素的任意祖先元素。当该祖先元素下的任意routerLink处于激活状态时,该祖先元素都将得到routerLinkActive指定的CSS类。下面的例子无论当前是处于联系人列表页仍是收藏页,<nav>标签都将得到.active类。示例代码以下:3d
RouterLink仅仅相应click事件,若是须要其余形式的跳转,在可使用Router对象的Router.navigateByUrl()或其兄弟方法Router.navigate()来完成。下面的例子实现了在进入联系人列表页1秒后自动跳转到收藏页的功能。示例代码以下:router
Router.navigateByUrl()和Router.navigate()的不一样之处在于传入的参数不一样,前者须要传入一个表示url的字符串或UrlTree类型的参数,后者和RouterLink指令同样,须要一个连接参数数组。对象
这两个方法除能够经过第一个参数来指定目标配置项外,还支持用extras参数定义跳转的具体行为。例如,若是想在不改变URL的状况下完成跳转,则能够经过如下代码来完成:blog
关于extras参数的其余用法,感兴趣的读者能够参考官方文档来了解更多的内容,在此再也不赘述。
在“组件”章节中介绍了如何使用@Input装饰器向组件传递数据,除此以外,Angular路由还提供了路由参数的功能,容许经过URL向组件传递数据。
顾名思义,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对象,容许对参数的更新进行订阅。示例代码以下:
咱们也能够经过解析URL的query部分来获取参数值。因为URL的query部分不用于和配置项进行匹配,所以每个配置项均可以拥有任意多个查询参数。下面的URL给联系人列表页定义了一个查询参数,表示只但愿在页面上显示5位联系人。
http://localhost:3000/list?limit=5
与Path参数相似,Query参数一样能够经过RouterLink指令或者跳转方法来赋值。示例代码以下:
Query参数的获取,须要借助于ActivatedRoute服务提供的Observable类型对象queryParams来完成。下面的代码片断展现了如何使用这个对象。
页面上全部组件均可以访问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提供了五类路由拦截:
关于路由拦截的内容会新开一个专题篇来说述这个功能的方方面面,这里先不赘述。
前文提到,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的加载方式由原来的延迟加载变动为预加载,而其余延迟加载模块并不会受到影响,仍是会等待用户触发时才加载。