1. 程式人生 > >Angular 5.x 系列教程筆記(二)——架構分析

Angular 5.x 系列教程筆記(二)——架構分析

前言

Angular 2.x 4.x 5.x 的逐個版本,遵循了模組化的思想,架構以及應用,相對於1.x的版本有了很大的改進,從專案中的使用來看,有很大的提升,今天我們就來看一下Angular 5.x架構的精髓所在。

主要的構造塊

Angular整體來講我們主要會學習到八個主要的構造塊,分別為模組,元件,模板,元資料,資料繫結,指令,服務,依賴注入,下面逐個來解釋一下:

模組

對於模組而言,整個應用至少存在一個根模組,模組是以@NgModule裝飾器的一個類,比如如下程式碼:

import { NgModule }       from '@angular/core';
import
{ BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard.component'; import { HeroDetailComponent } from './hero-detail.component'; import { HeroesComponent } from './heroes.component'
; import { HeroService } from './hero.service'; import { AppRoutingModule } from './app-routing.module'; @NgModule({ imports: [ BrowserModule, FormsModule, AppRoutingModule ], declarations: [ AppComponent, DashboardComponent, HeroDetailComponent, HeroesComponent ], providers
: [ HeroService ], bootstrap: [ AppComponent ] }) export class AppModule { }

於此同時,Angular 提供了一組 JavaScript 模組, 我們可以把它們看做庫模組,並且每個 Angular 庫的名字都帶有@angular字首,使用起來也比較方便,更加直觀。

元件

元件就是定義的一個通用類,通過一些由屬性和方法組成的 API 控制部分可以重用的檢視,例如下程式碼:

export class HeroListComponent implements OnInit {
  heroes: Hero[];
  selectedHero: Hero;

  constructor(private service: HeroService) { }

  ngOnInit() {
    this.heroes = this.service.getHeroes();
  }

  selectHero(hero: Hero) { this.selectedHero = hero; }
}

模板

Angular中模板以 HTML 形式存在,目的是告訴 Angular 如何渲染元件,如果編寫過HTML , CSS, 處理這個模組相當容易,除了普通的html屬性之外,還有一些特殊的屬性,比如使用其它元素。 例如,像*ngFor、{{hero.name}}、(click)、[hero]等, 都是Angular特有的屬性,只有Angular框架可以識別。

<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>

元資料

所謂的元資料,元資料告訴 Angular 如何處理一個類,常用的有@Component,其裡面的元資料會告訴 Angular 從哪裡獲取你為元件指定的主要的構建塊。

@Component({
  selector: 'my-app',
  template: `
    <h1>{{title}}</h1>
    <nav>
      <a routerLink="/dashboard" routerLinkActive="active">Dashboard</a>
      <a routerLink="/heroes" routerLinkActive="active">Heroes</a>
    </nav>
    <router-outlet></router-outlet>
  `,
  styleUrls: ['./app.component.css'],
})

資料繫結

用過Angular 1.x的同學,一定清晰的記得,Angular1.x 包括,雙向資料繫結,單向資料繫結,還有一次性資料繫結。
那麼在Angular 2.x + 中,主要有以下幾種形式:

  1. 屬性繫結和插值表示式 元件類-> 模板
  2. 事件繫結:模板 -> 元件類
  3. 雙向繫結: 模板 <-> 元件類
<li>{{hero.name}}</li>
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
<li (click)="selectHero(hero)"></li>

<input [(ngModel)]="hero.name">

在官方網站學習過程中,我們看到以上幾種方式,尤為注意的在雙向資料繫結中,使用ngmodel,需要額外引入模組

import { FormsModule }    from '@angular/forms';

指令

指令這個概念在1.x 版本尤為突出,也是1.x版本的一個重大的亮點和優勢,在2.x + 的版本中,元件其實就是一個帶模板的指令;
@Component裝飾器實際上就是一個@Directive裝飾器,只是擴充套件了一些面向模板的特性而已。

服務

服務即為Service, Factory,哈哈這是1.x的概念, 其實元件類應保持精簡,而且元件本身不從伺服器獲得資料、不進行驗證輸入,也不直接往控制檯寫日誌。那麼這一切改如何處理呢, 它們把這些任務委託給服務。在2.x 中,我們使用ts定義服務,並且注入,使用更為方便,如下就是我們練習縮寫的HeroService:

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;
  }
}

依賴注入

依賴注入不是什麼新鮮的概念,如果學過Java 三大框架,一定會有所瞭解Spring的應用原理,但是JS框架中,這是一個比較新的嘗試, 其中Angular 使用依賴注入來提供新元件以及元件所需的服務。

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

@Injectable()
export class HeroService {

}

Angular 通過檢視建構函式的引數型別得知元件需要哪些服務,當 Angular 建立元件時,會首先為元件所需的服務請求一個注入器 (injector)。

constructor(private service: HeroService) { }