官網地址:https://angular.io/docs/ts/latest/guide/architecture.html
結構圖

結構圖囊括了構成一個Angular2應用的八塊主要內容
Module
Module:模塊
Angular應用是模塊化的,通常我們的應用是由許多個模塊集合而成的。
一個典型的模塊,包含著一串只專注于實現一個目的的代碼,它會導出這串代碼中有價值的東西,最典型的是一個類。
我們之前(在demo2中)見識過了模塊導出一個組件類,由此可知組件類也是由模塊導出的東西之一。
大部分應用都含有一個<code>AppComponent</code>,通常,我們可以在一個名為<code>app.component.ts</code>的文件中找到它。文件中會有一句這樣的聲明:
export class AppComponent { }
這個<code>export</code>聲明告訴TypeScript,這是一個模塊,它擁有一個<code>AppComponent</code>類,這個類是公開的,并且可供應用中其他模塊進行調用。
當我們需要對<code>AppComponent</code>進行引用時,像這樣將它導入:
import { AppComponent } from './app.component';
<br />
Library Modules
一些模塊是另外一個模塊的庫。
Angular本身集結了許多模塊庫,他們被放在npm包中。他們的名字以<code>@angular</code>打頭。
<code>@angular/core</code>是一種常見的初級模塊庫,我們所需要的大部分東西都可以從中取得。
還有一些常見的模塊庫,比如
<code>@angular/common</code>,<code>@angular/router</code>,<code>@angular/http</code>等等。
我們導入庫的方法是類似的,比如我們導入Angular<code>Component
</code>函數
import { Component } from '@angular/core';
對比一下之前導入我們自己創建的<code>AppComponent</code>
import { AppComponent } from './app.component';
可以發現,路徑名是不同的。
Key
- Angular應用是一系列模塊構成的。
- 模塊總會導出一些東西,比如類、函數或者值,然后這些東西被其他的模塊所引用。
- 我們偏向于將應用寫成模塊的集合,一個模塊導出一樣東西(專注于一個目的)。
<br />
The Component
一個組件控制一個視圖。
例如,<code>HeroListComponent</code>,擁有一個<code>heroes</code>屬性,這個屬性從一個服務中返回一個heroes的數組。它還擁有一個<code>selectHero()</code>方法,這個方法在用戶從列表中點擊一個hero時,設置一個<code>selectedHero</code>屬性。
export class HeroListComponent implements OnInit {
constructor(private service: HeroService) { }
heroes: Hero[];
selectedHero: Hero;
ngOnInit() {
this.heroes = this.service.getHeroes();
}
selectHero(hero: Hero) { this.selectedHero = hero; }
}
Angular在用戶使用應用的時候,創建、更新、銷毀組件,開發者可以在這個生命周期的任一時刻采取任何行動。
<br />
The Template
我們在組件中定義template,一個template是HTML的一部分,它告訴Angular如何渲染組件。
一個template大部分與HTML很相似,但也有不同的地方。這是<code>HeroList</code>組件中的template。
<h2>Hero List</h2>
<p><i>Pick a hero from the list</i></p>
<div *ngFor="let hero of heroes" (click)="selectHero(hero)">
{{hero.name}}
</div>
<hero-detail *ngIf="selectedHero" [hero]="selectedHero"></hero-detail>
<code><hero-detail></code>標簽代表著<code>HeroDetailComponent</code>.
<code>HeroDetailComponent</code>可以說是<code>HeroListComponent</code>的孩子。Root Template中包含Child Component和Child Template,Child Template中又包含GrandChild Component和GrandChild Template.我們可以這樣將組件混合起來,利用原生的HTML元素,在同一個頁面中進行展示。
我們將組建復雜的組件樹,來創建我們功能豐富的應用。
<br />
Angular Metadata
Metadata告訴Angular如何處理一個類。
當我們回過頭來看<code>HeroListComponent</code>時,它像一個類,直到我們告訴Angular這是一個組件。我們使用給這個類附上metadata的方式來告訴Angular.
一個簡單有效的附帶metadata的方法是使用decorator。
@Component({
selector: 'hero-list',
templateUrl: 'app/hero-list.component.html',
directives: [HeroDetailComponent],
providers: [HeroService]
})
export class HeroesComponent { ... }
這里我們使用了<code>@Component</code>decorator.
一個decorator是一個函數。Decorators通常有一個構造參數。<code>@Component</code>decorator包含了一個對象,這個對象攜帶有Angular需要創建和展示的組件及其視圖的全部信息。
接下來我們看看<code>@Component</code>中可能包含的選項。
- selector
css選擇器告訴Angular在HTML找到<code><hero-list></code>標簽,在標簽里創建然后插入這個<code>HeroListComponent</code>的視圖。 - templateUrl
組件template所在地址,template是組件要展示出來的視圖。 - directives
template所需的Components或者Directives的一個數組。剛才我們提到,template希望Angular在<code><hero-detail></code>標簽出現的地方插入<code>HeroDetailComponent</code>,而只有當<code>HeroDetailComponent</code>在<code>directives</code>被提到之后,Angular才會按照我們所期待的那樣去做。 - providers
這是一個數組,數組中對組件所需的服務提供了依賴注入。可以使用這個方法來告訴Angular,我們的組件需要<code>HeroService</code>,這樣它可以從這個服務中獲得英雄列表來展示。
總結:The @Component function takes the configuration object and turns it into metadata that it attaches to the component class definition. Angular discovers this metadata at runtime and thus knows how to do "the right thing".
The template, metadata, and component together describe the view.
<br />
Data Binding

沒有框架的幫助時,我們需要將數據push進html,然后獲取用戶的響應動作,以此來更新數據。這樣手動實現push/pull邏輯是很乏味的。
Angular支持data binding,一種使得template和組件其他部分能夠相互協作的機制。
data binding語法有四種。這里我們展示了三種。
<div>{{hero.name}}</div>
<hero-detail [hero]="selectedHero"></hero-detail>
<div (click)="selectHero(hero)"></div>
interpolation在<code><div></code>標簽中展示了組件的<code>hero.name</code>屬性。
property binding 通過<code>[hero]</code>將父組件<code>HeroListComponent</code>的<code>selectedHero</code>,傳給了孩子組件<code>HeroDetailComponent</code>的屬性<code>hero</code>.
event binding <code>(click)</code>是一個事件綁定,它將在用戶點擊hero's name時調用<code>selectHero</code>方法。
Two-way data binding通過使用<code>ngModel</code>指令可以實現屬性和事件的結合綁定。
<input [(ngModel)]="hero.name">
用戶的輸入改變同樣會回傳給組件,造成組件中屬性的改變。


data binding在template與它的組件的溝通中起到了重大的作用。
<br />
The Directive
templates是動態變化的,當Angular對它進行渲染時,它根據directive給的指示對DOM做出改變。
一個 directive是一個有directive metadata的類。在Typescript中我們使用<code>@Directive</code>decorator來將metadata與類連接。
組件也是directive的一種。<code>@Component</code>decorator是含有template的一種<code>@Directive</code>decorator.
Directives中有兩種,我們稱之為"structural" 和 "attribute" 的directives.他們通常出現在HTML標簽中,就像attributes一樣。
Structural directives通過對DOM進行增添、移動、替代操作來展示視圖。
<div *ngFor="let hero of heroes"></div>
<hero-detail *ngIf="selectedHero"></hero-detail>
<code>*ngFor</code>告訴Angular用<div>對<code>heroes</code>列表中的每一個hero進行展示。
<code>*ngIf</code>只有當選中的hero存在時,包含<code>HeroDetail</code>.
Attribute directives對存在的元素進行外觀或者行為的操作。在template中,它們看起來就像常規的HTML attributes.
<input [(ngModel)]="hero.name">
<code>ngModel</code>改變了已經存在的元素<code><input></code>的行為,設置了它展示出來的屬性值,使它對輸入改變這個事件作出響應。
<br />
The Service
Service包含著大量我們所需要的函數、值、屬性。幾乎所有東西都可以成為service。service是一個擁有單一目的的類。舉例:
logging service
data service
message bus
tax calculator
application configuration
Angular自身沒有關于service的定義,也就是說,并沒有一個service的基類。
export class HeroService {
constructor(
private backend: BackendService,
private logger: Logger) { }
private heroes: Hero[] = [];
getHeroes() {
this.backend.getAll(Hero).then( (heroes: Hero[]) => {
this.logger.log(`Fetched ${heroes.length} heroes.`);
this.heroes.push(...heroes); // fill cache
});
return this.heroes;
}
}
<code>HeroService</code>依賴于<code>LoggerService</code>和<code> BackendService</code>.它fetch一個hero,并返回它。
組件是service的主要服務對象。它們依賴service去掌控細枝末節。它們將諸如從服務器獲取數據、驗證用戶輸入這樣的瑣事交給service。
Angular使得我們將應用邏輯寫入service變得簡單,并且通過依賴注入使得service對組件是可用的。
<br />
Dependency Injection
"Dependency Injection"是一種提供類的新實例的方式,它包含了類所需的所有依賴。大部分依賴都是service。Angular給component提供它們所需的service.
constructor(private service: HeroService) { }
當Angular創建一個新的組件時,它首先會向Injector要求組件所需的service。
一個Injector掌控含有預先創建的service實例的容器。如果所需service不在這個容器中,injector會在對Angular響應之前創建一個,并把它加入到容器中。當Angular得到了所有所需的service,將這些service作為參數傳入到組件構造器中。

當沒有<code>HeroService</code>時,如何創建一個service?
簡要地說,我們必須有一個事先注冊好的<code>HeroService</code>的provider,provider可以創建或者返回service。
我們可以再應用組件樹的任何一層注冊provider。我們通常在根部完成此事,在我們bootstrap我們的應用時。這樣這個service的實例就可以在任何位置被調用了。
bootstrap(AppComponent, [BackendService, HeroService, Logger]);
bootstrap是啟動和配置根應用組件的方法。
key
- injector掌控一個含有它創建的service實例的容器。
injector可以利用provider創建一個它沒有的service實例。 - provider對于創建service來說就像食譜。
- 我們通過injector注冊provider.