每次點擊連接或瀏覽器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以後發生了什麼,你會知道該說什麼。
但願有讀者喜歡!