Angular5是一個很是強大的前端框架,學習曲線較陡,掌握了不一樣模塊(主要指Component)之間的通訊機制,就等於掌握了Angular5。下面詳盡列舉各類通訊方式供您參考:javascript
使用場景:頁面加載,自動顯示title的值,字號爲h3。css
html標籤,花括號裏面的是模板表達式(template expression):html
<h3>{{title}}</h3>
ts代碼,寫在Component類內部:前端
title = "前端編程"。
使用場景:頁面加載,自動顯示圖片。<img scr="{{imageUrl}}" style="height:30px">
ts代碼:imageUrl="http://xxx.xxx.com/1.png";
java
使用場景:如按鈕的點擊事件:<button (click)="onSave($event)">保存</button>
ts代碼:express
onSave(event) { .... }
使用場景:利用第三方Component展現某個對象的細節編程
Angular5不容許綁定到一個不一樣Component的屬性,除非使用@Input或者(之後說)@Output顯式地申明。數組
好比傳遞一個當前的收貨地址到一個地址細節的Component:瀏覽器
<app-address-detail [address]="currentAddress"></app-address-detail>
ts代碼:@Input() address: Address;
ruby
使用場景:頁面一部分一個點擊事件,致使另外一部分產生變化
好比:點擊一個按鈕,顯示點擊次數,其中顯示點擊次數的邏輯由另一個Component負責。
子Component代碼:
@Component({ selector: 'app-number', template: `<b>{{message}}</b>` }) export class NumberComponent { message: string = ''; count: number = 0; increaseByOne() { this.count = this.count + 1; this.message = "次數: " + this.count; }
@Component({ selector: 'app-number', template: `<b>{{message}}</b>` }) export class NumberComponent { message: string = ''; count: number = 0; increaseByOne() { this.count = this.count + 1; this.message = "次數: " + this.count; }
父template:
<button type="button" (click)="increase()">增長</button>
<app-number></app-number>
父Component代碼:
export class NumberParentComponent { @ViewChild(NumberComponent) private numberComponent: NumberComponent; increase() { this.numberComponent.increaseByOne(); } }
export class NumberParentComponent { @ViewChild(NumberComponent) private numberComponent: NumberComponent; increase() { this.numberComponent.increaseByOne(); } }
使用場景:點擊頁面一部分,另外一部分顏色發生變化
須要獲取Directive所在的整個元素(element),在Directive方法內部,修改那個元素的Dom屬性,顏色。
子Directive代碼:
@Directive({ selector: '[chColor]' }) export class ChColorDirective implements AfterViewInit{ constructor(private elementRef: ElementRef) { } ngAfterViewInit(){ this.elementRef.nativeElement.style.color = 'green'; } change(changedColor: String){ this.elementRef.nativeElement.style.color = changedColor; } }
@Directive({ selector: '[chColor]' }) export class ChColorDirective implements AfterViewInit{ constructor(private elementRef: ElementRef) { } ngAfterViewInit(){ this.elementRef.nativeElement.style.color = 'green'; } change(changedColor: String){ this.elementRef.nativeElement.style.color = changedColor; } }
父Template代碼:
<p chColor>改變個人顏色</p>
<div>
修改顏色:
<input type="button" name="red" (click)="changeColor('red')"> 紅色
</div>
使用場景:好比刪除一組子Component,每一個子Com前面有checkbox。
父Component的Template:
<section>
<h4 *ngIf="todos.getAll().length">Todo列表</h4>
<todo-item *ngFor="let todo of todos.getAll()" [todo]="todo"></todo>
</section>
父component代碼:
export class TodoAppComponent implements AfterViewInit { @ViewChildren(TodoComponent) todoComponents: QueryList<TodoComponent>; constructor(private todos: TodoList) {} ngAfterViewInit() { // viewChildren在這個地方變得可用 }
export class TodoAppComponent implements AfterViewInit { @ViewChildren(TodoComponent) todoComponents: QueryList<TodoComponent>; constructor(private todos: TodoList) {} ngAfterViewInit() { // viewChildren在這個地方變得可用 }
由於Angular的DOM編譯器會先處理父Component,而後再處理children,這樣在初始化的時候,todosComponent是未定義的,undefined。他們的值在ngAfterViewInit函數裏面設置。好比把獲取到的todosComponent編程數組再賦值給todos。
得到了子Component列表以後,就能夠按照需求處理了。
使用場景:父Component往子Component裏面插入一塊Html
往什麼地方插呢?這是由<ng-content>標籤訂義了插槽。
子Card Component的Template:
<div class="card"> <!--單槽插入點--> <ng-content></ng-content> </div>
<div class="card"> <!--單槽插入點--> <ng-content></ng-content> </div>
父Component的Template:
<card> <!--下面是動態內容--> <div class="card-content"> <p>This is dynamic content</p> </div> </card>
<card> <!--下面是動態內容--> <div class="card-content"> <p>This is dynamic content</p> </div> </card>
使用場景:父Component往子Component裏面插入多塊Html內容,插入地點由selector匹配
子Card Component的Template:
<div>
<!--tag-->
<ng-content select="header"></ng-content>
<!--css 選擇器-->
<ng-content select="div.body"></ng-content>
<!--attribute-->
<ng-content select="[card][body]"></ng-content>
<!--帶值的attribute-->
<ng-content select="[card-type=body]"></ng-content>
</div>
父Component的Template:
<card>
<header>...</header>
<div class="body">我是body</div>
<div body card>...</div>
<div card-type="body">...</div>
</card>
使用場景:在第二個children裏面獲取第三個Component信息
@Component({ selector: 'app-footer', template: '<ng-content></ng-content>' }) class FooterComponent{} @Component(...) class TodoAppComponent implements AfterContentInit { @ContentChild(FooterComponent) footer: FooterComponent; ngAfterContentInit() { // this.footer now points to the instance of 'FooterComponent' } } @Component({ selector: 'demo-app', template: ` <content> <todo-app> <app-footer> <small>Yet another todo app!</small> </app-footer> </todo-app> </content> ` }) export class AppComponent{}
@Component({ selector: 'app-footer', template: '<ng-content></ng-content>' }) class FooterComponent{} @Component(...) class TodoAppComponent implements AfterContentInit { @ContentChild(FooterComponent) footer: FooterComponent; ngAfterContentInit() { // this.footer now points to the instance of 'FooterComponent' } } @Component({ selector: 'demo-app', template: ` <content> <todo-app> <app-footer> <small>Yet another todo app!</small> </app-footer> </todo-app> </content> ` }) export class AppComponent{}
這裏AppComponent使用TodoAppComponent並在它的一對tag之間傳遞FooterComponent給它,咱們稱FooterComponent是TodoAppComponent的content child。
使用場景:父Component刪除子Component,可是刪除操做在子Component上,好比一個按鈕。
子Component暴露一個EventEmitter爲屬性,而後綁定到父Component的一個函數,綁定以後,父Component就開始偵聽這個事件了。
子Component:
@Component({ template: ` <div> <button (click)="delete()">刪除</button> </div>` }) export class HeroDetailComponent{ // this component makes a request but it can't actually delete a hero deleteRequest = new EventEmitter<Hero>(); delete() { this.deleteRequest.emit(this.hero); } }
@Component({ template: ` <div> <button (click)="delete()">刪除</button> </div>` }) export class HeroDetailComponent{ // this component makes a request but it can't actually delete a hero deleteRequest = new EventEmitter<Hero>(); delete() { this.deleteRequest.emit(this.hero); } }
父Component的Template:<app-hero-detail (deleteRequest)="deleteHero($event)" [hero]="currentHero">
當子Component觸發事件時,Angular調用父Component的deleteHero方法,把要傳遞的hero做爲$event變量傳遞出來。
使用場景:獲取一行子Html並修改該Html屬性,顏色
Template代碼:
<div>
姓名:<input type="text" #name><br/>
</div>
ts代碼:
export class ExampleComponent implements AfterViewInit { @ViewChild('name') private name: ElementRef; ngAfterViewInit() { this.name.nativeElement.style.color = 'red'; } }
export class ExampleComponent implements AfterViewInit { @ViewChild('name') private name: ElementRef; ngAfterViewInit() { this.name.nativeElement.style.color = 'red'; } }
使用場景:地址列表,還有兩個按鈕(上一個,下一個地址)瀏覽歷史地址,不但願每切換一個地址都從新建立一個新的地址Component,而是複用一個地址Component。
當router建立新的Component時,會調用ngOnInit()函數,這樣寫:
this.address = this.route.paramMap .switchMap(params: ParamMap) => this.service.getAddress(params.get('id')));
this.address = this.route.paramMap .switchMap(params: ParamMap) => this.service.getAddress(params.get('id')));
這裏this.service.getAddress返回一個Observable<Address>對象。
使用場景:地址列表,從列表中每選擇一個,切換爲該地址的詳細信息,若是想顯示另一個地址的詳細信息,必須先回到列表頁面;這頁意味着每選擇一個地址都從新建立一個新的地址Component實例。
let id = this.route.snapshot.paramMap.get('id'); this.address = this.service.getAddress(id);
let id = this.route.snapshot.paramMap.get('id'); this.address = this.service.getAddress(id);
使用場景:須要傳遞參數的場景太多,不可能每個參數都對應一個route,若是那樣的話路由配置會至關複雜,這時候可選參數就派上用場了,不須要更改路由配置。
觀察地址欄,可選參數不一樣於路由參數,也不是查詢參數,而是矩陣參數,矩陣參數也是一個標準,並不是angular發明的,形式以下:;id=15;foo=foo
發送端ts代碼:this.router.navigate(['/list', {id: addressId, foo: 'foo'}]);
接收端仍是經過ActivatedRoute獲取地址Id:
this.addresses = this.route.paramMap .switchMap(params: ParamMap) => // (+) before 'params.get()' turns the string into a number this.selectedId = +params.get('id'); return this.service.getAddresses(); });
this.addresses = this.route.paramMap .switchMap(params: ParamMap) => // (+) before 'params.get()' turns the string into a number this.selectedId = +params.get('id'); return this.service.getAddresses(); });
使用場景:一個Html tag,好比p,應用了一個Directive,當用戶鼠標移到這個p上面,高亮這個p元素;鼠標移開,取消高亮。
分析這個需求,要求Directive能監聽到Host元素的事件(Hover, Leave等),這是@HostListener的做用,把@HostListener放到某個函數前面,當事件發生時就會調用這個函數。
Template:<p appHighlight>點亮我</p>
Directive代碼:
@HostListener('mouseenter') onmouseenter() { this.hightlight('yellow'); } @HostListener('mouseleave') onmouseleave() { this.highlight(null); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }
@HostListener('mouseenter') onmouseenter() { this.hightlight('yellow'); } @HostListener('mouseleave') onmouseleave() { this.highlight(null); } private highlight(color: string) { this.el.nativeElement.style.backgroundColor = color; }
以上設置背景顏色的方式假定了咱們的程序運行在瀏覽器環境下。可是Angular瞄準的是跨平臺,因此Angular提供了一種平臺獨立的方式來設置因素的屬性,Renderer2正是用於這種目的。this.render.setStyle(el.nativeElement, 'width', '200px');
使用場景:更改Host元素的外觀或者行爲,經過把Directive內部的屬性和Host元素的屬性綁定起來,實現了,內部屬性一發生變化,Host元素相應的屬性就會發生變化。
Directive代碼:@HostBinding('class.card-outline')private isHovering: boolean;
而後在Directive內部的事件處理函數中更改isHovering的值,從而間接改變Host元素的屬性。
使用場景:由一個Component導航到另一個Component,可能要事先到服務器取出數據,若是數據存在,則繼續導航;若是不存在,則取消導航,Resolver就是取數據的。
路由配置:
path: 'crisis-center',
component: CrisisCenterComponent,
children: [
{
path: '',
Component: CrisisListComponent,
children: [
{
path: ':id',
component: CrisisDetailComponent,
canDeactivate: [CanDeactivateGuard],
resolve: {
crisis: CrisisDetailResolver
}
}
}
];