前言
同上篇,這篇也是寫玩具 (side project) 時遇到的需求,麵包屑 (Breadcrumbs) 這個功能亦是網站相當常見的元素,那麼又該如何透過 Angular 的 Router 搭配 Bootstrap 4 建立麵包屑呢?
本文環境
- Angular CLI: 8.3.20
- Angular: 8.2.14
- Bootstrap: 4.3.1
實作
說明
因為這個需求源自於我的玩具 (side project) ,而麵包屑的做法在網路上查完一輪後,因人而異的有各種方式能實作,所以本文的做法僅供參考。
如同上一段提到的,這個專案環境使用懶載入的方式載入模組 (lazy-loading-ngmodules) ,而網路上查到的資料卻很少提到在這個前提下應該怎麼調整,導致照著做是無法順利運行的。
又爬了好一陣的資料,折騰了好久才完成,但完成的版本需要再麵包屑元件的 constructor(){}
內進行 router.events
的訂閱。
但根據查到的資料,constructor(){}
指的是物件實體剛被建立時,此時是不包含在生命週期中的,而 constructor(){}
應該只做依賴注入,不要亂加一些東西。
想想,又對於這個做法不滿意,想辦法改良後最後決定放在這邊記錄下來。
routing.module 設置
在各個父層路由定義 data
物件內容,如:
app-routing.module
1 | const routes: Routes = [ |
back-routing.module
1 | const routes: Routes = [ |
訂閱 Router events
在 AppComponent
中訂閱 Router
的事件, 而這些事件相當多,在此只需要針對 NavigationEnd
進行處理即可。
另外要記得在 ngOnDestroy()
階段取消訂閱。
接著還需要一隻服務 BreadcrumbService
將資料存下來,供 BreadcrumbComponent
使用
app.component
1 | import { Component, OnInit, OnDestroy } from '@angular/core'; |
當 event
為 NavigationEnd
時,透過 setActivatedRouteRoot()
將資料儲存。
新增 Breadcrumb Service
breadcrumb-service
1 | import { Injectable, EventEmitter } from '@angular/core'; |
當 setActivatedRouteRoot()
被觸發時,將資料 emit
出去,這時 BreadcrumbComponent
只需要訂閱 routeEvent
事件就好了~
建立 BreadcrumbComponent
接著來處理本次的主角:
- 依賴注入
BreadcrumbService
- 在
ngOnInit()
內 訂閱BreadcrumbService
的routeEvent
事件,確保資料的取得- 由於是在
ngOnInit()
階段訂閱,所以程式首次運行必須跑一次getActivatedRouteRoot()
- 由於是在
- 在
ngOnDestroy()
階段取消訂閱 - 運用遞迴的技巧取回顯示在麵包屑上的內容
將取回的資料印出觀察,會發現路由的資料其實是一層層包覆的資料結構
breadcrumb.component.html
1 | <nav aria-label="breadcrumb"> |
breadcrumb.component.ts
1 | import { Component, OnInit, OnDestroy } from '@angular/core'; |
特別要注意如果是使用懶載入模組的方式,則需要判斷
child.component
否則會有麵包屑名稱重複的問題,原因參考資料中有提到,有興趣的不妨看看。
參考資料
這篇文章參考的內容
結論
成果圖:
本文不會有完整程式碼提供下載,僅紀錄相關程式碼片段,如果之後這個玩具有完成,會再考慮要不要公開。