我們整理專案後,現在專案有更明確的模組來封裝元件,不僅讓 App 效能提升,也讓專案更「語意化」了,並且也越來越有架構的感覺了對吧?
不過來有很多 Angular 好玩常用的功能我們沒有使用到。今天,我們相規劃一個新的功能模組,並且先列出一個概要與對應的 Angular 功能。
讓我們開始吧!
(欸欸欸,我又想到一個新的東西...)
呃,我以為做夢的是我...好吧,妳又夢見了什麼?
(先別過什麼青銅五小強了,我這幾天除了看紀錄片外,也讀了一點書。)
所以妳夢見了什麼?
(我們可以來培訓英雄啊!)
是沒錯啦,但是培訓人是有成本的。
(不不不,我們要讓他們自己付錢。)
呃,所以妳是讀到了什麼書啊?
(哼哼,我發現只要來蓋一個地下城,一切就解決了!讓人類來付錢挑戰地下城!)
哦?我倒是沒有想過妳可以這樣接回「主線」。
(所以現在立刻去抓四條龍,放在最後幾層...)
妳等會吧!我們應該先規劃這個要有哪些功能吧!
地下城除了邂逅之外,每層都會有個樓主,只有打敗樓主才能繼續往下一層推進。
我們先設定守護地下城的都是怪物,很合理吧。所以我們會有一個新增怪物的功能,因為我們在新增英雄的時候,使用了去範本驅動表單(Template Driven Forms),所以這次讓我們來玩玩響應式表單(Reactive Forms)。接著,我們要提供設定樓主的功能。
而怪物或提供一個列表,可供篩選檢視,這部分會使用 Mat-Table來實作,但是...它預設提供的分頁器(pagination)是長這個樣子的:
這當然是好的設計,但可能我們已經很習慣點選一個頁面方塊來切換分頁,例如 iT邦幫忙的分頁器。當然除了「分頁」功能之外,還有很多設計元件的細節,也許都會讓我們應用到 Angular 更多樣化的技術。比如,當你的分頁氣支援多國語,又會出現類似這樣的文字「共 a 頁,第 b 頁」(page b of a),你該如何讓畫面依據語言來做不同的呈現?如果我撐得到那天,就來分頁一下吧。
接著,要實作「在通過這一層之前,無法前往下一層」,每一層我們會由路由來控制,因此這裡我們將使用路由守衛來把控使用者的訪問,當使用者不具備挑戰下一層的權限時,拒絕他的訪問。
接著我們要製作簡易的網頁遊戲來進行頭目戰,
地下城待辦清單:
目前列出來的清單,讓我覺得或許應該再把「怪物」拉出來做成一個功能模組,而自訂元件應該是一個專案等級的共用元件,這部分我們將新增一個 Shared Module 來宣告此類元件、指令、管道...。
這是我們計劃中的專案結構:
src
⌞app
⌞ hero
⌞ monsger
⌞ stratum
⌞ shared
shared.module.ts
⌞ models
⌞ pipes
⌞ directives
⌞ services
hero.service.ts
簡單說完接下來的規劃,我們即將使用響應式表單(Reactive Form)製作新增怪物功能,先簡單比較一些範本驅動表單和響應式表單吧。
用個簡易的表格來看:
項目 | 範本驅動表單| 響應示表單
------------- | -------------
所屬模組 | FormsModule | ReactoveFormsModule
建立表單方式 | 宣告式(Declarative Programming) | 編程式(Imperative Programming)
檢核器 | 提供基礎的檢核器 | 可以撰寫複雜的檢核邏輯
使用場景 | 易於使用,方法類似原生的 HTML 表單,適合簡單的表單 | 適合處理複雜邏輯的表單
除了這些以外,我自己認為,範本驅動表單不一定要與資料綁定,這件事我覺得挺有意思的。或許說不上什麼優點,但想想——在真的確定資料輸入正確,並將其發送、傳遞到後端儲存之前,這些經過檢核、編輯的資料,其實並沒有真的綁定資料。想想就覺得好玩,莫名有種買空賣空的趣味。
不過,讓我先來看一段響應式表單的程式碼範例,感受感受一下:
this.monsterForm = new FromGroup({
'name': new FormControl(null, [Validators.required]),
'hp': new FormControl(null, [Validators.required]),
...
})
也許我們還不真的了解上面這段程式碼發生了什麼事(大致上應該可以猜出來),但可以很直覺得地發覺響應式表單會將表單的預設值、結構、檢核方式設定在 ts 檔案中。其他暫且不提,但在了解表單結構這件事上,我認為響應式表單是更方便的——更別說還提供了 FormBuilder 這麼好的類別,簡化了設定響應式表單節的方式,例如:
constructor(private formBuildder: FormBuilder) {}
this.monsterForm = this.formBuilder.group({
name: [null, [Validators.required]],
hp: [null, [Validators.required]],
...
)
});
並且,FormBuilder 搭配編輯器,可以更好地提供我們程式開發指引。如果選用響應式表單,建議就注入 FormBuilder 來使用。