Angular2初識

Imagine_Dragon發表於2020-12-14

檔案結構

檔案結構

啟動過程

image.png

元件(Component)

image.png

在angular中,一個元件由四個檔案組成,例如每個angular專案都會有的app根元件,就由以下四個檔案組成

  • app.component.css
  • app.component.html
  • app.component.spec.ts
  • app.component.ts

image.png

元件的後設資料

後設資料告訴Angular如何處理元件類

image.png

模板與檢視

模板就是一種 HTML,它會告訴 Angular 如何渲染該元件。

模板語法

模板很像標準的 HTML,但是它還包含 Angular 的模板語法,這些模板語法可以根據你的應用邏輯、應用狀態和 DOM 資料來修改這些 HTML。 你的模板可以使用資料繫結來協調應用和 DOM 中的資料,使用管道在顯示出來之前對其進行轉換,使用指令來把程式邏輯應用到要顯示的內容上。

<h2>Hero List</h2>

<p><i>Pick a hero from the list</i></p>
<ul>
  <li *ngFor="let hero of heroes" (click)="selectHero(hero)">
    {{hero.name}}
  </li>
</ul>

<app-hero-detail *ngIf="selectedHero" [hero]="selectedHero"></app-hero-detail>

這個模板使用了典型的 HTML 元素,比如 <h2> 和 <p>,還包括一些 Angular 的模板語法元素,如 *[ngFor],{{hero.name}}click[hero]`。這些模板語法元素告訴 Angular 該如何根據程式邏輯和資料在螢幕上渲染 HTML。

  • *[ngFor](https://angular.cn/api/common/NgForOf) 指令告訴 Angular 在一個列表上進行迭代。

  • {{hero.name}}(click) 和 [hero] 把程式資料繫結到及繫結回 DOM,以響應使用者的輸入。更多內容參閱稍後的資料繫結部分。

  • 模板中的 <app-hero-detail> 標籤是一個代表新元件 HeroDetailComponent 的元素。 HeroDetailComponent(程式碼略)定義了 HeroListComponent 的英雄詳情子檢視。 注意觀察像這樣的自定義元件是如何與原生 HTML 元素無縫的混合在一起的。

資料繫結(Data Binding)

image.png

<li>{{hero.name}}</li>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<li (click)="selectHero(hero)"></li>
<input [(ngModel)]="hero.name">

上述四種資料繫結方式分別為:

  • {{hero.name}} 這個插值在 <li> 標籤中顯示元件的 hero.name 屬性的值。
  • [hero]屬性繫結把父元件的 selectedHero 的值傳到子元件的 hero 屬性中。
  • (click) 事件繫結會呼叫元件的 selectHero 方法。
  • [ngModel]雙向資料繫結(主要用於模板驅動表單中),它會把屬性繫結和事件繫結組合成一種單獨的寫法。

指令

image.png

管道

image.png

模組(Module)

image.png

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ Logger ],
  declarations: [ AppComponent ],
  exports:      [ AppComponent ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

服務

服務是一個廣義的概念,它包括應用所需的任何值、函式或特性。狹義的服務是一個明確定義了用途的類。它應該做一些具體的事,並做好。

Angular 把元件和服務區分開,以提高模組性和複用性。 通過把元件中和檢視有關的功能與其它型別的處理分離開,你可以讓元件類更加精簡、高效。

理想情況下,元件的工作只管使用者體驗,而不用顧及其它。 它應該提供用於資料繫結的屬性和方法,以便作為檢視(由模板渲染)和應用邏輯(通常包含一些模型的概念)的中介者。

元件應該把諸如從伺服器獲取資料、驗證使用者輸入或直接往控制檯中寫日誌等工作委託給各種服務。通過把各種處理任務定義到可注入的服務類中,你可以讓它被任何元件使用。 通過在不同的環境中注入同一種服務的不同提供者,你還可以讓你的應用更具適應性。

Angular 不會強迫你遵循這些原則。Angular 只會通過依賴注入來幫你更容易地將應用邏輯分解為服務,並讓這些服務可用於各個元件中。

下面是一個服務類的範例,用於把日誌記錄到瀏覽器的控制檯

# src/app/logger.service.ts
export class Logger {
  log(msg: any)   { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any)  { console.warn(msg); }
}

服務也可以依賴其它服務。比如,這裡的 HeroService 就依賴於 Logger 服務,它還用 BackendService 來獲取英雄資料。BackendService 還可能再轉而依賴 [HttpClient]服務來從伺服器非同步獲取資料。

# src/app/hero.service.ts
export class HeroService {
  private heroes: Hero[] = [];

  constructor(
    private backend: BackendService,
    private logger: Logger) { }

  getHeroes() {
    this.backend.getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }
}

依賴注入(dependency injection)

與spring的依賴注入一樣

簡單理解為,當你需要使用一個服務,函式或值時,不需要自己手動引入,可以通過angular注入到屬性中去,直接使用。比如 HeroListComponent 的建構函式中需要 HeroService:

# src/app/hero-list.component.ts
constructor(private service: HeroService) { }

提供服務

對於要用到的任何服務,你必須至少註冊一個提供者。服務可以在自己的後設資料中把自己註冊為提供者,這樣可以讓自己隨處可用。或者,你也可以為特定的模組或元件註冊提供者。要註冊提供者,就要在服務的 @[Injectable]() 裝飾器中提供它的後設資料,或者在 @[NgModule]() 或 @[Component]() 的後設資料中。

@Injectable({
  providedIn: 'root',
})

當你使用@NgModule 註冊提供者時,該服務的同一個例項將會對該 NgModule 中的所有元件可用。要想在這一層註冊,請用 @[NgModule]() 裝飾器中的 providers 屬性:

@NgModule({
  providers: [
   BackendService,
   Logger
 ],
 ...
})

當你在元件級註冊提供者時,你會為該元件的每一個新例項提供該服務的一個新例項。 要在元件級註冊,就要在 @[Component]() 後設資料的 providers 屬性中註冊服務提供者。

@Component({
  selector:    'app-hero-list',
  templateUrl: './hero-list.component.html',
  providers:  [ HeroService ]
})