繼續筆記001,繼續研究下去。這篇會研讀 <aio-top-menu>
component
aio-top-menu
component 所在路徑 src/app/layout/top-menu
1 | import { Component, Input } from '@angular/core'; |
- 由
app.component.ts
提供要顯示的資料
1 | export interface NavigationNode { |
app.component.ts
提供 <aio-top-menu>
的資料來源是 navigationService.navigationViews
1 | this.navigationService.navigationViews.subscribe(views => { |
在 navigationService
內的 navigationView
方法如下
1 | const navigationInfo = this.fetchNavigationInfo(); |
fetchNavigationInfo
1 | const navigationPath = CONTENT_URL_PREFIX + 'navigation.json'; |
其實這段很有趣,以下是程式碼裡的註解,詳細說明為什麼他們要這樣子寫
Get an observable that fetches the
NavigationResponse
from the server. We create an observable by callinghttp.get
but then publish it to share the result among multiple subscribers, without triggering new requests. We usepublishLast
because once the http request is complete the request observable completes. If you usepublish
here then the completed request observable will cause the subscribed observables to complete too. Weconnect
to the published observable to trigger the request immediately. We could use.refCount
here but then if the subscribers went from 1 -> 0 -> 1 then you would get another request to the server. We are not storing the subscription from connecting as we do not expect this service to be destroyed.
publishLast()
只會記錄 Observable 完成後的值。connect()
會立即執行 Obervable。
透過這兩個 Operator 的組合就可以避免重複發出 request,又可以保留最後的資料。
1 | export type NavigationResponse = {__versionInfo: VersionInfo } & { [name: string]: NavigationNode[]|VersionInfo }; |
這種 type
的定義方式為 TypeScript 的 Intersection Types
,意思是指當指定到這種型別時,需同時符合第一種及第二種型別。
而在這 function 內所取得的資料來源 (generated/navigation.json),就是符合這種格式的。
getNavigationViews
繼上一段取完資料後的 Observable,接著會傳進這個 function,這 function 的功能是將關於 View 的部分抽離出來
1 | private getNavigationViews(navigationInfo: Observable<NavigationResponse>): Observable<NavigationViews> { |
Object.assign({}, response)
將原有的資料複製成一份全新的map
裡的行為是將 __versionInfo 的部分從既有的資料中刪除- 使用
publishLast()
跟connect()
的理由同上一段 - 回傳的結果,就只會剩下
NavigationViews
而已
1 | export interface NavigationViews { |
接著回到 app.component.ts
,在 subscribe 之後就可以取得 NavigationViews
了
1 | this.navigationService.navigationViews.subscribe(views => { |
所以 topmenuNodes
就透過 KeyValue 的形式從 NavigationViews 中取出並讓 <aio-top-menu>
做顯示的動作