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 + 中,主要有以下幾種形式:
- 屬性繫結和插值表示式 元件類-> 模板
- 事件繫結:模板 -> 元件類
- 雙向繫結: 模板 <-> 元件類
<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) { }