iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 7
4
Modern Web

Angular 深入淺出三十天系列 第 7

[Angular 深入淺出三十天] Day 06 - 基礎結構說明(一)

「原來 Angular 這麼好玩啊?!」Wayne 做完練習後,開心地跟我說道。

「是不是?!之後如果寫再複雜一點的應用更能體現出 Angular 厲害的地方!」我信心滿滿地說。

「不過完成了這個應用之後,我更好奇 Angular 是怎麼運作的了!」Wayne 好奇地說。

「那就先從目前有實作過的東西來解釋吧!我跟你說...」


NgModule

Angular 是一個很注重模組化開發的框架,它有著自己特有的模組系統-NgModule

而每個用 Angular 寫出來的應用程式,至少都會有一個 NgModule 的類別-根模組 (Root Module) 。通常我們會把這個根模組取名為 AppModule,且這個根模組會放在 app.module.ts 這支檔案裡 (其實這些事情,Angular CLI 都幫我們處理好了)

雖然一個小一點、簡單一點的應用程式,可能只會有一個 NgModule,但大多數的應用程式都還會有著其他大大小小、各式各樣的功能模組。

拿我們寫過的 MTRStationList 的 AppModule 來簡單說明一下:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

// Component
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

在 Angular 裡,我會將一個檔案大致上切分為三個區塊。

首先是引入的區塊:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

// Componet
import { AppComponent } from './app.component';

要引入 (import) 的程式碼都放在這個區塊 (我個人喜歡分類並加上註解)

再來是裝飾器(Decorator)區塊:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})

裝飾器一開始是 Typescript 為了 Angular 先行加入的功能,JavaScript 則是直到 ES7 才確定加入的新功能(關於裝飾器,TypeScript 可以參考官方文件,JavaScript 的部份則可以參考此篇文章)。

傳入裝飾器裡的物件,在 Angular 裡稱作中繼資料 (MetaData) ,用來告訴 Angular 要怎麼樣處理接下來的的類別。

要傳入 @NgModule 裝飾器內的中繼資料大致上會有以下幾個較常用的屬性:

  • declarations-屬於此 NgModule 的 Component、Directive 與 Pipe 皆放置於此。

  • imports-此 NgModule 需要使用、依賴的其他 NgModule 皆放置於此(好像有點饒舌)。

  • providers-可以被整個應用程式中的任何部分被使用的 Service 皆放置於此,也可以將 Service 直接放置在 Component 的 Metadata 裡的 providers (但放置在不同地方會有一些需要特別注意的事項,後續在說明 Service 時會提到。另外,在 Angular 6 之後,在 Service 之中也可以使用 Metadata 裡的 providedIn 宣告,該 Service 要 provided 到哪裡。詳細可以參考此篇文章或是隔壁棚Angular 大師之路也有提到)

  • exports-此處放置的是,當在其他 NgModule 裡 import 了當前的 Module 後,可以在其他 NgModule 裡的 Component Template 使用的 Component、Directive 與 Pipe。

  • entryComponents-放在這裡的元件通常是用不通過 Route 的方式,而採用動態加入的元件。

  • bootstrap-在此設置的是應用程式通常稱之為 Root Component (根元件) ,而且只有 Root Module 才要設置此屬性。

最後則是類別(Class):

export class AppModule { }

每個檔案都會有一個要 export 給別人使用的類別,像上述範例的就是要將 AppModule 這個類別 export 出去讓其他人使用 (Root Module 實際上也只會被 main.ts 引用)

隔壁棚也有篇文章在解說 NgModule,點我多學一點!


Component

在 Angular 的世界裡,Component 負責定義與控制畫面,令其可以根據資料和程式邏輯呈現相對應的畫面。

一樣拿我們寫過的 MTRStationList 的 AppComponent 來簡單說明一下:

import { Component } from '@angular/core';

// Constant
import { stationList } from './station-list.const';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  /**
   * 所有列車到站站名之資料
   *
   * @memberof AppComponent
   */
  list = stationList;

}

還記得在介紹 NgModules 時,我有提到過我會將一個檔案分成三個區塊嗎?沒錯!這裡也是一樣分成三個區塊。不過這次不重複說明其他兩個區塊,我們將重點擺在裝飾器的部份:

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

有注意到嗎?之前 NgModule 的裝飾器名稱就叫做 @NgModule,而 Component 的裝飾器名稱就改為叫做 @Component 了!

謎之音:廢話!!(飛踢)

而且傳入 @Component 中的 Metadata 也跟 @NgModule 的不一樣!

謎之音:還是廢話!!(再飛踢)

不過一樣的是,傳入的 Metadata 都是為了告訴 Angular,要怎麼處理接下來的類別。

謎之音:到底哪來這麼多廢話!!(過肩摔)

而要傳入 @Component 裡的 Metadata ,大致會有以下幾個比較常用的屬性(鼻青臉腫地說):

  • selector-CSS 選擇器,它告訴 Angular 在 Template 中找到相應的位置之後,創建並插入該Component 的實體。以上述的例子來說,Angular 會在 Template 中尋找 <app-root></app-root> 這樣子的標籤,然後創建出 AppComponent 的實體並將其插入其中。

  • templateUrl-此 Component 的 Template 檔案位置 (相對位置)

  • template-跟 templateUrl 的用途類似,只是 templateUrl 的值是檔案的位置,這裡是直接放 HTML 的語法 (如非必要,不建議使用)

  • styleUrls-光看名字就覺得是跟 templateUrl 類似的東西。沒錯!一樣是檔案位置,只不過換成是樣式檔而已。

  • styles-跟 styleUrlstemplate 類似,這裡可以直接放 CSS 的語法 (如非必要,不建議使用)

  • providers-跟 NgModule 的 providers 類似。但要注意的是,在 NgModule 的 providers 裡宣告的 Service (或是直接在 Service 的 provideIn 宣告為 'root'),整個應用程式的生命週期只會有一個實體 (類似 singleton 的概念) ;但在此處宣告的 Service,實體數量是跟該 Component 的實體數量一致的。


參考資料


上一篇
[Angular 深入淺出三十天] Day 05 - Angular 小學堂(一)
下一篇
[Angular 深入淺出三十天] Day 07 - 基礎結構說明(二)
系列文
Angular 深入淺出三十天33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
SuperMike
iT邦新手 5 級 ‧ 2019-05-24 16:13:53

@Component裡面預設沒有顯示 template、styles和providers,請問會有手動加入的時機嗎?

  • template 其實都在 templateUrl 指定的檔案設計了
  • styles 其實都在 styleUrls 指定的檔案設計了
  • 至於 providers,Service 應該都是在@NgModule加入的吧?

所以這三個應該都不會有手動加入的時機囉?

Leo iT邦新手 3 級 ‧ 2019-05-28 12:01:41 檢舉

Hi SuperMike,

之所以預設都是用 xxxUrl 的方式,就是因為 Google 想要引導大家把檔案切割出來,以便在協作或是後續維護時方便大家處理,不易於產生衝突。

所以如果今天你覺得該 Component 的 template 真的很簡單,或是你不想要將檔案切割出去自成一個 html 檔的話,其實就可以用 template 這個屬性來替代 templateUrl ;而 style 的部份也是同一個道理。

至於 providers ,則是跟 Service 的生命週期有相關,後續我在基礎結構說明(四)的時候會提到。

我要留言

立即登入留言