每次点击连接或浏览器URL改变时,Angular路由器都会确保应用程序作出相应的反应。 react
为了作到这一点,Angular路由器执行如下7个步骤的顺序:浏览器
解析(Parse):它解析用户要导航到的浏览器URL。数据结构
重定向(Redirect):它应用URL重定向(若是定义了一个)ide
标识(Identify):它标识哪一个路由器状态对应于URL。svg
警卫(Guard):它运行在路由器状态中定义的守卫。函数
解析(Resolve):它解决路由器状态所需的数据。ui
激活(Activate):它激活Angular组件来显示页面。atom
管理(Manage):它管理导航,并在请求新URL时重复该过程。url
记住这7个步骤,您可使用助记PRIGRAM,其中每一个字母表明路由过程当中的一步:spa
Parse
Redirect
Identify
Guard
Resolve
Activate
Manage
在咱们深度了解每一步以前,让咱们回顾一下,Angular路由器的使用术语。
路由服务(router service): 咱们应用程序中的Angular全局路由服务
路由器配置(router configuration):咱们应用程序中的全部可能的路由器状态的定义
路由器状态(router state):路由器在某个时间点的状态,表示为激活的路由快照树。
激活的路由快照(activated route snapshot):提供对路由器状态节点的URL、参数和数据的访问
守护(guard):在加载、激活或停用路由时运行的脚本(script)。
解析器(resolver):在请求页面被激活以前获取数据的脚本
路由器插座(router outlet):在DOM中,Angular路由器能够放置激活组件的位置
URL片断(URL segments):URL斜杠部分
若是你不熟悉Angular路由器或任何这些术语听起来陌生,我强烈建议你先阅读Use Angular router to resolve data,官方路由指导或Angular主力做者Victor Savkin的书Angular Router
就Angular路由器而言,浏览器URL是表示路由器状态的字符串。因为路由器状态是一棵树,Angular路由器本质上考虑了浏览器URL的序列化树。
在路由过程的第1步中,Angular路由器将浏览器URL解析为URL树。
URL树是一种数据结构,稍后将帮助Angular路由器识别步骤3中的路由器状态树。
为了解析URL,Angular使用如下约定:(注:冒号前面是路由器出口,后面是URL片断)
/ => 斜线划分URL片断
() => 括号指定次要路径。
: => 冒号指定一个指定的路由器出口。
; => 一个分号指定一个矩阵参数。
? => 一个问号分隔查询字符串参数。
'#'=> 一个#号标签列举片断。
'//'=> 双斜线分割多个次要路径。
例如,在解析下面的URL时:
/section-one;test=one/(nav:navigation;test=two//main:about;test=three)?query=four#frag
angular识别出如下部分(点击这里获取更大的版本):
'section-one', 'navigation' 和 'about' 是URL片断
';test=one', ';test=two' 和 ';test=three' 是矩阵参数
'(nav:navigation;test=two)' 是次要路由,列出了出口路由'nav'的 URL片断'navigation',以及分配了本身的矩阵参数test,值为字符串类型的'two'
(main:about;test=three) 是次要路由,列出了出口路由'main'的 URL片断'about',以及分配了本身的矩阵参数test,值为字符串类型的'three'
'//' 用于分隔二级路由。
'?query=four' 分配查询字符串变量'query',字符串值为'four'
'#frag' 分配了片断'frag'
矩阵参数的范围是在路由同级(Matrix parameters are scoped on a route level. )。不一样的路由能够具备相同名称和不一样值的矩阵参数。
相反,查询字符串参数和URL片断的范围不在路由同级(query string parameters and the fragment are not scoped on a route level)。它们经过路由共享,所以它们的名称应该是惟一的。
一旦Angular路由器组装了URL树,它将继续到步骤2。
在Angular路由器使用URL树建立路由器的状态以前,它会检查对应的重定向规则。
有两种不一样的重定向类型:
local redirect:
当 'redirectTo' 不是以 '/' 开始
替换成单个URL片断
例如: { path: 'one', redirectTo: 'two' }
absolute redirect:
当 'redirectTo' 是以 '/' 开始
替换整个URL
例如: { path: 'one', redirectTo: '/two' }
Angular路由器遍历路由器配置。一旦找到匹配的重定向,重定向就被应用,路由器继续到步骤3。
只有一种重定向规则被应用!
若是路由1重定向到路由2,路由2重定向到路由3,而后路由2重定向路由3不执行,路由2被激活。(If route 1 redirects to route 2, which in turn redirects to route 3, then the second redirect to route 3 is not performed and route 2 is activated.)
此时,Angular路由器拥有一个潜在重定向应用程序的URL树。
Angular路由器遍历URL树,并与路由器配置中配置的路径匹配URL片断。
若是URL片断与路由的路径匹配,则路由的子路由与剩余的URL片断匹配,直到全部URL片断匹配为止。
若是没有找到彻底匹配的路由器,回溯到在下一个兄弟的路由找到匹配。
思考下面的路由器配置:
[ { path: 'one', component: OneComponent, children: [ { path: 'two/three', component: OtherComponent ] } ]
和下面的URL:
/one/two/three
而后Angular路由器会找到一个由两条路由组成的匹配:
路径为'one' 的路由与一个URL片断匹配
路径为'two/three' 的子路由与两个URL片断匹配
一旦Angular路由器找到一个完整的匹配,消耗全部的URL段,路由器状态被构造,路由器继续到步骤4。
请注意,Angular路由器没有路由精度的概念。一旦找到完整的匹配,Angular路由器中止处理配置。所以,确保您的路由按正确的顺序配置是很重要的。若是您将通配符路由做为第一个路由添加,则不会到达其余路由,通配符路由将始终匹配。所以,您应该始终将通配符路由添加为路由器配置中的最后一条路由。
若是整个路由器配置被处理且没有匹配,则路由器导航失败并记录错误。
如今Angular路由器知道要路由哪一个路由器状态,它就运行相关的守护程序来检查是否容许导航到新的路由器状态。
首先,它从'最深的子路由'到'顶级'的顺序运行下面的守卫进程:
CanDeactivate
CanActivateChild
而后, 它从'顶级'到'最深的子路由'的顺序运行下面的守卫进程:
CanActivate
若是新的路由器状态须要一个模块被延迟加载,那么下面的守护进程也是运行的:
CanLoad
一个守护者必须返回一个布尔值或一个承诺/可观察到的值,该值解析为布尔值。
当守护进程返回false值,导航就会被取消。
若是没有一个守卫返回一个false值,Angular路由器继续到步骤5。
由于Angular路由器知道新的路由器的状态能够被激活,它运行相关的resolvers。
在配置过程当中,可使用路由的数据属性将静态数据附加到路由:
{ path: 'one', component: OneComponent, data: { name: 'Jazz' } }
它容许你在运行时动态地解析数据。而后将新解析的数据合并到数据属性中的现有静态数据中:
path: 'one', component: OneComponent, data: { name: 'Jazz' }, resolve: { // Return value of AddressResolver will be merged in data // and will be available as data.address address: AddressResolver }
resolver 是一个函数或类,具备一个返回值、一个承诺或一个可观察对象。若是解析器返回一个承诺或一个可观察对象,Angular路由器在它继续到步骤6以前等待它完成。
一旦全部的resolve都已完成,其返回值是合并的路径的data property, 而后Angular路由器继续步骤6。
在这步里,Angular路由器实例化所需组件并将它们放在DOM中<router-outlet>
元素正确的相应路由器出口 。
若是一个组件已经在之前的路由器状态实例化过或者仅仅路由参数发生改变,那么组件就不会从新实例化。可是组件一样被从新激活( reactivated ), 并且新的参数能够经过可观察对象activatedroute进行使用。
当全部组件被实例化或从新激活时,Angular路由器会更新浏览器URL中的URL。
最后,当新的路由器状态被显示到屏幕上时,Angular路由器侦听URL更改和状态更改。
一旦发生下列状况之一:
用户更改浏览器URL
用户点击一个连接(使用 routerlink
)
执行导航命令(使用 router.navigate
)
Angular路由器重复整个过程。
在这篇文章中咱们学到了当用户导航从一个页面到另外一个的时候,Angular路由器都作了哪些过程。
你可使用助记 PRIGRAM:
Parse
Redirect
Identify
Guard
Resolve
Activate
Manage
记住Angular路由器通过的步骤的顺序。
了解这个过程将有助于您更好地了解幕后发生的事情,并帮助您调试潜在的路由问题。
下次有人问你,Guard以前或Resolve以后发生了什么,你会知道该说什么。
但愿有读者喜欢!