angular quick start tutorial summary

Angular Home

angular.cn
angular.io
angular-in-memory-web-api

Creat

你使用 CLI 創建了第二個組件 HeroesComponent。
ng generate component heroes
你把 HeroesComponent 添加到了殼組件 AppComponent 中,以便顯示它。
app.component.html <app-heros></app-heros>
你使用 UppercasePipe 來格式化英雄的名字。
heros.component.html <h2>{{hero.name | uppercase}} Details</h2>
你用 ngModel 指令實現了雙向數據綁定。
<input [(ngModel)]="hero.name" placeholder="name">
你知道了 AppModule。
添加元數據的地方,Angular 需要知道如何把應用程序的各個部分組合到一起,以及該應用需要哪些其它文件和庫。 這些信息被稱爲元數據(metadata)
你把 FormsModule 導入了 AppModule,以便 Angular 能識別並應用 ngModel 指令。
app.module.ts import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
imports: [
BrowserModule,
FormsModule
],

你知道了把組件聲明到 AppModule 是很重要的,並認識到 CLI 會自動幫你聲明它。
@NgModule({ declarations: [AppComponent,HerosComponent],。。。})

Display

英雄指南應用在一個主從視圖中顯示了英雄列表。
click事件 html <li *ngFor="let hero of heroes" (click)="onSelect(hero)">
ts onSelect(hero: Hero): void {this.selectedHero = hero;}

用戶可以選擇一個英雄,並查看該英雄的詳情。
<input [(ngModel)]="selectedHero.name" placeholder="name">
你使用 *ngFor 顯示了一個列表。
<li *ngFor="let hero of heroes" [class.selected]='hero === selectHero' (click)="onSelect(hero)">
你使用 *ngIf 來根據條件包含或排除了一段 HTML。
<div *ngIf='selectHero'></div>
你可以用 class 綁定來切換 CSS 的樣式類。
[class.selected]='hero === selectHero'

Master/Detail

你創建了一個獨立的、可複用的 HeroDetailComponent 組件。
ng generate component hero-detail
你用屬性綁定語法來讓父組件 HeroesComponent 可以控制子組件 HeroDetailComponent。
import { Hero } from '../hero';
@Input() hero: Hero;

你用 @Input 裝飾器來讓 hero 屬性可以在外部的 HeroesComponent 中綁定
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
import { Input } from '@angular/core';

Service

你把數據訪問邏輯重構到了 HeroService 類中。
組件不應該直接獲取或保存數據, 它們應該聚焦於展示數據,而把數據訪問的職責委託給某個服務
你在根模塊 AppModule 中提供了 HeroService 服務,以便在別處可以注入它。
ng generate service hero --module=app //not insert automatically
import { HeroService } from './hero.service';
@NgModule({providers: [HeroService]})

你使用 Angular 依賴注入機制把它注入到了組件中。
heroes.component.ts: import { HeroService } from '../hero.service';
constructor(private heroService: HeroService) { }

你給 HeroService 中獲取數據的方法提供了一個異步的函數簽名。
服務是在多個“互相不知道”的類之間共享信息的好辦法
回調函數,可以返回 Promise(承諾),也可以返回 Observable(可觀察對象)
你發現了 Observable 以及 RxJS 庫。
import { Observable, of } from 'rxjs';
你使用 RxJS 的 of() 方法返回了一個模擬英雄數據的可觀察對象 (Observable<Hero[]>)。
getHeroes(): Observable<Hero[]> {
this.messageService.add('HeroService: fetched heroes');
return of(HEROES);
}

在組件的 ngOnInit 生命週期鉤子中調用 HeroService 方法,而不是構造函數中。
讓構造函數保持簡單,只做初始化操作,比如把構造函數的參數賦值給屬性。 構造函數不應該做任何事
你創建了一個 MessageService,以便在類之間實現鬆耦合通訊。
ng generate service message --module=app
HeroService 連同注入到它的服務 MessageService 一起,注入到了組件中。
hero.service.ts: import { MessageService } from './message.service';
constructor(private messageService: MessageService) { }
export class HeroesComponent implements OnInit {
constructor(private heroService: HeroService) {}
ngOnInit() {this.getHeroes();}
getHeroes(): void {this.heroService.getHeroes().subscribe(heroes => this.heroes = heroes);}
}

Router

添加了 Angular 路由器在各個不同組件之間導航。
ng generate module app-routing --flat --module=app
你使用一些 <a>鏈接和一個<router-outlet> 把 AppComponent 轉換成了一個導航用的殼組件。
app.component.html
<nav>
<a routerLink="/dashboard">DashBoard</a>
<a routerLink="/heroes">Heroes</a>
</nav>
<router-outlet></router-outlet>

你在 AppRoutingModule 中配置了路由器。
const routes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'heroes', component: HeroesComponent },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'detail/:id', component: HeroDetailComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)]...
})

你定義了一些簡單路由、一個重定向路由和一個參數化路由。
{ path: 'heroes', component: HeroesComponent },
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: 'detail/:id', component: HeroDetailComponent },

你在 <a> 元素中使用了 routerLink 指令。
dashboard.component.html&heroes.component.html
<a routerLink="/detail/{{hero.id}}">

你把一個緊耦合的主從視圖重構成了帶路由的詳情視圖。
hero-detail.component.ts
export class HeroDetailComponent implements OnInit {
@Input() hero: Hero;
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location) { }
ngOnInit() {
this.getHero();
}
getHero(): void {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
}

你使用路由鏈接參數來導航到所選英雄的詳情視圖。
getHero(): void {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}

在多個組件之間共享了 HeroService 服務。
hero.service.ts//讀取數據的服務
use: dashboard.component.ts&heroes.component.ts&hero-detail.component.ts

HTTP

你添加了在應用程序中使用 HTTP 的必備依賴。
hero.service.ts
import { HttpClient, HttpHeaders } from '@angular/common/http';
constructor(
private http: HttpClient,
private messageService: MessageService) { }

你重構了 HeroService,以通過 web API 來加載英雄數據。

getHeroes(): Observable<Hero[]> {
return this.http.get<Hero[]>(this.heroesUrl) //return of(HEROES);
.pipe(
tap(heroes => this.log(`fetch heroes`)),
catchError(this.handleError('getHeroes', [])
));
}

你擴展了 HeroService 來支持 post()、put() 和 delete() 方法。
hero.service.ts
updateHero(hero: Hero): Observable<any> {
return this.http.put(this.heroesUrl, hero, httpOptions).pipe(
tap(() => this.log(`update hero id = ${hero.id}`)),
catchError(this.handleError<any>('updateHero'))
);
}
addHero(hero: Hero): Observable<Hero> {
return this.http.post<Hero>(this.heroesUrl, hero, httpOptions).pipe(
tap(() => this.log(`add hero w/ id=${hero.id}`)),
catchError(this.handleError<Hero>('addHero'))
);
}
deleteHero(hero: Hero | number): Observable<Hero> {
const id = typeof hero === 'number' ? hero : hero.id;
const url = `${this.heroesUrl}/${id}`;
return this.http.delete<Hero>(url, httpOptions).pipe(
tap(() => this.log(`delete hero id=${id}`)),
catchError(this.handleError<Hero>('deleteHero'))
);
}

你修改了組件,以允許用戶添加、編輯和刪除英雄。
heroes.component.html
<label>Hero Name:
<input #heroName>
</label>
<button (click)="add(heroName.value);heroName.value=''">add</button>
heroes.component.ts
add(name:string):void{
name=name.trim();
if(!name) return;
this.heroService.addHero({name} as Hero)
.subscribe(hero=>{this.heroes.push(hero);});
}

你配置了一個內存 Web API。
npm install angular-in-memory-web-api --save
app.module.ts
import { HttpClientInMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';
in-memory-data.service.ts
import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
construct (){}
createDb() {
const heroes = [
{ id: 11, name: 'Mr. Nice' } ];
return {heroes};
}
}

你學會了如何使用“可觀察對象”。
通常,Observable 可以在一段時間內返回多個值。
但來自 HttpClient 的 Observable 總是發出一個值,然後結束,再也不會發出其它值。
使用 RxJS 的 catchError() 操作符來建立對 Observable 結果的處理管道(pipe)
import { catchError, map, tap } from 'rxjs/operators';
現在,使用 .pipe() 方法來擴展 Observable 的結果,並給它一個 catchError() 操作符。
getHeroes (): Observable<Hero[]> {
return this.http.get<Hero[]>(this.heroesUrl)
.pipe(
catchError(this.handleError('getHeroes', []))
);
}

使用 RxJS的tap查看Observable中的值,使用那些值做一些事情,並且把它們傳出來.這種tap回調不會改變這些值本身
/** GET heroes from the server */
getHeroes (): Observable<Hero[]> {
return this.http.get<Hero[]>(this.heroesUrl)
.pipe(
tap(heroes => this.log(`fetched heroes`)),
catchError(this.handleError('getHeroes', []))
);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章