Angular 模塊都是一個(gè)帶有@NgModule裝飾器的類。
NgModule是一個(gè)裝飾器函數(shù),它接收一個(gè)用來描述模塊屬性的元數(shù)據(jù)對象。把緊隨其后的類標(biāo)記為模塊類。其中最重要的屬性是:
- declarations
聲明本模塊中擁有的視圖類。包括[組件]、[指令]和[管道]。 - exports(根模塊則不需要導(dǎo)出任何東西。)
導(dǎo)出可用于其它模塊的組件[模板]。 - imports(Angular模塊)
本模塊聲明的組件模板需要的類所在的其它模塊。 - providers
[服務(wù)]的創(chuàng)建者,并加入到全局服務(wù)列表中,可用于應(yīng)用任何部分。 - bootstrap
指定應(yīng)用的主視圖(稱為根組件),它是所有其它視圖的宿主。只有根模塊才能設(shè)置bootstrap屬性。
app.module.ts中bootstrap了AppComponent,而main.ts文件中bootstrap了AppModule
元數(shù)據(jù)告訴 Angular 如何處理一個(gè)類。我們用裝飾器 (decorator) 來附加元數(shù)據(jù)。@Component裝飾器,它把緊隨其后的類標(biāo)記成了組件類。
@Component的配置項(xiàng)包括:
selector:CSS 選擇器,在父級(jí) HTML 中查找對應(yīng)內(nèi)容,創(chuàng)建并插入該組件。
<li>{{hero.name}}</li> 插值綁定
<hero-detail [hero]="selectedHero"></hero-detail> 屬性綁定
<li (click)="selectHero(hero)"></li> 事件綁定
<input [(ngModel)]="hero.name"> 雙向綁定
組件是一種特殊的指令
“依賴注入”是提供類的新實(shí)例的一種方式,還負(fù)責(zé)處理好類所需的全部依賴。大多數(shù)依賴都是服務(wù)
@Injectable()
變量賦值的方式初始化組件,也可以使用構(gòu)造函數(shù)來聲明和初始化屬性。
插值表達(dá)式
<img title="{{heroImageUrl}}">
等價(jià)于
<img [title]="heroImageUrl">
等價(jià)于
<img bind-title="heroImageUrl">
其他同理
事件綁定
<button (click)="onSave()">Save</button>等價(jià)于
<button on-click="onSave()">On Save</button>
<div (myClick)="clickMessage=$event" clickable>click with myClick</div>
<button (click)="onSave($event)">Save</button>//模板對象
<button *ngFor="let hero of heroes" (click)="deleteHero(hero)">{{hero.name}}</button>//模板輸入變量
<form #heroForm (ngSubmit)="onSubmit(heroForm)"> ... </form>//模板引用變量
Class設(shè)置
<div [class.special]="isSpecial">Special</div>
或者[class]="isSpecial"
或者
<div [ngClass]="currentClasses">This div is initially saveable</div>
其中currentClasses是一個(gè)對象,每個(gè)key都是類名,value是布爾值
<button [style.color]="isSpecial ? 'red' : 'green'">
或者
<div [ngStyle]="currentStyles">This div is initially italic</div>
其中currentStyles是一個(gè)對象,
this.currentStyles = {
'font-style': this.canSave ? 'italic' : 'normal',
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
'font-size': this.isSpecial ? '24px' : '12px'
};
[()]都是雙向綁定,而[(ngModel)]依賴[FormsModule]
ngIf指令通常會(huì)用來防范空指針錯(cuò)誤。
ngSwitch
<div [ngSwitch]="currentHero.emotion">
<happy-hero *ngSwitchCase="'happy'" [hero]="currentHero"></happy-hero>
<sad-hero *ngSwitchCase="'sad'" [hero]="currentHero"></sad-hero>
<confused-hero *ngSwitchCase="'confused'" [hero]="currentHero"></confused-hero>
<unknown-hero *ngSwitchDefault [hero]="currentHero"></unknown-hero>
</div>
引用變量
<input #phone placeholder="phone number">或者
<input ref-phone placeholder="phone number">
<button (click)="callPhone(phone.value)">Call</button>
模板引用變量的作用范圍是整個(gè)模板。 不要在同一個(gè)模板中多次定義同一個(gè)變量名,否則它在運(yùn)行期間的值是無法確定的。
輸入和輸出屬性
@Input() hero: Hero;
@Output() deleteRequest = new EventEmitter<Hero>();
或者
@Component({
inputs: ['hero'],
outputs: ['deleteRequest'],
})
指定別名
@Output('myClick') clicks = new EventEmitter<string>();
或者
@Directive({
outputs: ['clicks:myClick'] // propertyName:alias
})
管道操作符
類似過濾器
將obj渲染在頁面:
<div>{{currentHero | json}}</div>
安全導(dǎo)航操作符( ?. )
{{name}}如果name不存在,則僅僅不渲染
但是{{hero.name}}的hero如果不存在,則直接報(bào)錯(cuò),因此可以采用NgIf環(huán)繞保護(hù),或直接
生命周期鉤子函數(shù)
OnInit()鉤子:
在構(gòu)造函數(shù)之后馬上執(zhí)行復(fù)雜的初始化邏輯
OnChanges() 鉤子:
一旦檢測到該組件(或指令)的輸入屬性發(fā)生了變化,Angular就會(huì)調(diào)用它的ngOnChanges()方法。
每個(gè)組件的css只對自身生效
:host為宿主元素偽類選擇器,可以選中該組件的宿主元素
指定的styleUrlsURL是相對于應(yīng)用程序根目錄的,它通常是應(yīng)用的宿主頁面index.html所在的地方。
Angular的<ng-container>是一個(gè)分組元素,但它不會(huì)污染樣式或元素布局,因?yàn)?Angular 壓根不會(huì)把它放進(jìn) DOM 中。
一般配合*ngFor使用,給其提供一個(gè)宿主
$event.target即事件對象元素自身
<input #box (keyup)="0">
<p>{{box.value}}</p>
只有在應(yīng)用做了些異步事件(如擊鍵),Angular 才更新綁定(并最終影響到屏幕)。將keyup事件綁定到了數(shù)字0,這是可能是最短的模板語句。 雖然這個(gè)語句不做什么,但它滿足 Angular 的要求,所以 Angular 將更新屏幕。
事件(keyup.enter)只關(guān)注回車鍵事件
(blur)事件
<form #heroForm="ngForm">
Angular會(huì)在<form>標(biāo)簽上自動(dòng)創(chuàng)建并附加一個(gè)[NgForm]指令。
此時(shí)每個(gè)input元素都應(yīng)該有唯一的name屬性,否則報(bào)錯(cuò)
NgModel 指令不僅僅跟蹤狀態(tài)。它還使用特定的 Angular CSS 類來更新控件,以反映當(dāng)前狀態(tài):
控件被訪問過。
ng-touched ng-untouched
控件的值變化了。
ng-dirty ng-pristine
控件的值有效。
ng-valid ng-invalid
<button type="button" class="btn btn-default" (click)="newHero(); heroForm.reset()">New Hero</button>
.reset()方法重置表單.使各狀態(tài)重置且清空表單內(nèi)容,尤其是變成ng-pristine
<button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>
<input id="name" class="form-control"
formControlName="name" required >
<div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert alert-danger">
<div *ngIf="name.errors.required">
Name is required.
</div>
<div *ngIf="name.errors.minlength">
Name must be at least 4 characters long.
</div>
<div *ngIf="name.errors.forbiddenName">
Name cannot be Bob.
</div>
</div>
不要將 Angular 模塊的imports數(shù)組與文件頂部的import語句弄混淆了。它們的功能不同。
JavaScript 的import聲明允許你訪問在其他文件中導(dǎo)出的符號(hào),這樣你可以在當(dāng)前文件引用它們。 我們會(huì)往幾乎所有類型的應(yīng)用中加入import語句。 它們與 Angular 毫無關(guān)系,Angular 對它們也一無所知。
模塊的imports數(shù)組是@NgModule元數(shù)據(jù)中獨(dú)有的。它告訴 Angular 特定 Angular 模塊的信息 — 用@NgModule裝飾的類 — 應(yīng)用需要它們來正常工作。
Angular 模塊把組件、指令和管道打包成內(nèi)聚的功能塊,每個(gè)模塊聚焦于一個(gè)特性區(qū)域、業(yè)務(wù)領(lǐng)域、工作流或通用工具。
每個(gè)運(yùn)行在瀏覽器中的應(yīng)用都必須導(dǎo)入[BrowserModule],他注冊了一些關(guān)鍵的應(yīng)用服務(wù)提供商。 它還包括了一些通用的指令,例如[NgIf]和[NgFor],所以這些指令在該模塊的任何組件模板中都是可用的。
啟動(dòng)模塊為根模塊,自定義的其他模塊叫特性模塊。