亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

@angular/router 源碼分析之注冊(cè)路由

hidogs / 1551人閱讀

摘要:模塊主要解決程序路由狀態(tài)改變和懶加載模塊問(wèn)題。本文主要解釋程序啟動(dòng)后,是如何注冊(cè)開(kāi)發(fā)者定義的路由集合的,和實(shí)例化對(duì)象的。第六個(gè)重要的對(duì)象就是,提供了初始導(dǎo)航功能。

@angular/router 模塊主要解決程序路由狀態(tài)改變和懶加載模塊問(wèn)題。

比如,程序從路由狀態(tài) state1: /advisors/1/households/1 轉(zhuǎn)變?yōu)槁酚蔂顟B(tài) state2: /advisors/1/accounts/2,需要實(shí)例化的組件集合也從 components1: Advisor+Household 轉(zhuǎn)變?yōu)?components2: Advisor+Account(準(zhǔn)確的說(shuō)應(yīng)該是先是 Module 的實(shí)例化,然后才是組件的實(shí)例化),這個(gè)過(guò)程是如何實(shí)現(xiàn)的?

另外,對(duì)于按需加載的模塊,又該如何加載該模塊,并且將該模塊顯示在對(duì)應(yīng)位置處?

@angular/router 模塊就是用來(lái)解決路由狀態(tài)改變和懶加載模塊問(wèn)題的。本文主要解釋程序啟動(dòng)后,@angular/router 是如何注冊(cè)開(kāi)發(fā)者定義的路由集合的,和實(shí)例化 Router 對(duì)象的。

程序啟動(dòng)后,即調(diào)用 PlatformRef.bootstrapModule(AppModule) 后,會(huì)執(zhí)行導(dǎo)入的 RouterModule.forRoot(routes: Routes) 來(lái)合并 RouterModule 提供的服務(wù),且 routes 路由集合是由開(kāi)發(fā)者自定義的,比如:

routes: Routes = [
    {path: "advisors/:id", component: AdvisorComponent, children: [
        {path: "households/:id", component: HouseholdComponent},
        {path: "accounts/:id", component: AccountComponent},
    ]},
];

一起看看 RouterModule 能給我們提供哪些重點(diǎn)對(duì)象吧:RouterModule.forRoot(routes)。

第一個(gè)對(duì)象是來(lái)自于 @angular/common 的 Location,用來(lái)表示瀏覽器的 url,并提供了 forward(),back(),go() 等重要方法用來(lái)改變 url,同時(shí)提供了 HashLocationStrategyPathLocationStrategy 兩種策略生成是否帶有 "#" 的 url,至于為何需要兩種不同風(fēng)格的 url 原因可以看 中文官網(wǎng)描述;

第二個(gè)對(duì)象是序列化 URL 的對(duì)象 UrlSerializer,@angular/router 使用 UrlTree 對(duì)象存儲(chǔ)一個(gè) URL,比如 "/advisors/1/accounts/2?type=loan#fragment",并且 UrlTree 對(duì)象又使用 UrlSegmentGroup 對(duì)象來(lái)表示 URL 的 path 部分,這里 UrlSegmentGroup 表示的就是 "/advisors/1/accounts/2" 這部分,UrlSegmentGroup 對(duì)象也可以存儲(chǔ) "/advisors/1/accounts/2/(user/john//bank:abc)?type=loan#fragment" 這樣的多重 URL,該多重 URL 可以表示為兩個(gè) URL: "/advisors/1/accounts/2/user/john?type=loan#fragment""/advisors/1/accounts/2/abc?type=loan#fragment"(該 URL 的出口 outlet 是 bank),雖然是多重 URL,但只需要用一個(gè)對(duì)象 UrlSegmentGroup 就可以存儲(chǔ),而 UrlSegmentGroup 又使用 Segment 對(duì)象來(lái)表示當(dāng)前 group 內(nèi)的每一個(gè) "/" 之間的部分。Url 的格式可見(jiàn)下圖:

對(duì)于上圖中的 URL,@angular/router 會(huì)調(diào)用 Router.parseUrl(), 實(shí)際上還是調(diào)用 UrlSerializer.parse() 來(lái)把 URL 字符串 "/section-one;test=one/(nav:navigation;test=two//main:about;test=three)?query=four#frag" 解析為 UrlTree 對(duì)象:

@angular/router 使用 UrlTree 對(duì)象來(lái)存儲(chǔ) URL 字符串,并使用 UrlSerializer 來(lái)解析和序列化 URL。這塊知識(shí)點(diǎn)還是很重要的。

第三個(gè)對(duì)象 Router,也是 @angular/router 模塊中最重要的對(duì)象,使用 setupRouter 方法來(lái)初始化 Router,初始化邏輯主要是它的 構(gòu)造函數(shù),開(kāi)發(fā)者自定義的 routes 集合 也是作為依賴來(lái)構(gòu)造 Router 對(duì)象。第一個(gè)點(diǎn)就是首先調(diào)用 createEmptyUrlTree 方法創(chuàng)建一個(gè) 空的 UrlTree;第二個(gè)點(diǎn)就是實(shí)例化一個(gè)路由加載器 loader,當(dāng)開(kāi)發(fā)者定義了 route.loadChildren 屬性時(shí),該 loader 就會(huì)使用 loader.load() 方法去異步加載模塊,所以該 loader 對(duì)象是用來(lái)解決懶加載問(wèn)題的;第三個(gè)點(diǎn)是調(diào)用 createEmptyState 方法創(chuàng)建一個(gè)空 RouterState,RouterState 對(duì)象表示當(dāng)前激活路由的狀態(tài)(RouterState is a tree of activated routes.),它也是一個(gè)樹(shù)形數(shù)據(jù)結(jié)構(gòu),用來(lái)存儲(chǔ) 當(dāng)前激活路由 的數(shù)據(jù),該樹(shù)的節(jié)點(diǎn)使用 ActivatedRoute 對(duì)象表示,比如對(duì)于上文中開(kāi)發(fā)者定義的路由列表,當(dāng) URL 為 "/advisors/1/households/1" 時(shí),這時(shí) RouterState 對(duì)象表示的狀態(tài)樹(shù),如下紅色顯示部分的子樹(shù),而每一個(gè)包含組件的層級(jí)即是 ActivatedRoute

第四個(gè)點(diǎn)是調(diào)用 processNavigations() 執(zhí)行路由狀態(tài)切換,實(shí)際上 @angular/router 的作用就是控制路由狀態(tài)的切換,所以 整個(gè) @angular/router 的核心代碼就是 processNavigations() 方法。該方法訂閱了一個(gè) BehaviorSubject 對(duì)象,只要該 BehaviorSubject 流對(duì)象彈射出一個(gè)新值,就會(huì)運(yùn)行 executeScheduledNavigation(),不管是不是刷新 URL,都會(huì)運(yùn)行 runNavigate(),所以精確的說(shuō),runNavigate() 這一百行左右代碼才是 @angular/router 包最最核心的代碼。這一百來(lái)行代碼具體分為幾個(gè)步驟:

1. Apply redirects(relative/absolute)

2. Construct router state by current URL(這段也就是第二篇文章將要探討的 查找路由 邏輯)

3. PreActivation: Run Guard3. PreActivation: Run Resolver

4. Activation: Activate Components(這段也就是第三篇文章將要探討的 運(yùn)行路由 邏輯)

第四個(gè)重要的對(duì)象就是模塊工廠加載器 NgModuleFactoryLoader,該對(duì)象來(lái)自于 @angular/core 核心包,主要用來(lái)輔助 RouterConfigLoader 對(duì)象,懶加載模塊時(shí)可以異步加載遠(yuǎn)程模塊。

第五個(gè)重要的對(duì)象就是提供了預(yù)加載對(duì)象 RouterPreloader,用來(lái)預(yù)加載所有懶加載模塊,從而提高性能。

第六個(gè)重要的對(duì)象就是 RouterInitializer,提供了初始導(dǎo)航功能。當(dāng)程序首次初始化和啟動(dòng)時(shí),調(diào)用 RouterInitializer.appInitializer()RouterInitializer.bootstrapListener() 來(lái)進(jìn)行初始化導(dǎo)航,最后還是調(diào)用 Router.initialNavigation() 來(lái)首次導(dǎo)航到 URL 對(duì)應(yīng)的 RouterState。

所以,@angular/router 首次初始化時(shí),提供的最重要對(duì)象是 Router,其他一切對(duì)象和邏輯都是圍繞著 Router 對(duì)象展開(kāi)。@angular/router 是如何根據(jù)當(dāng)前 URL 查找到對(duì)應(yīng)的 route 的呢?見(jiàn)本系列第二篇文章。

云服務(wù)器 GPU云服務(wù)器