本文爲原創,轉載請註明出處: cnzt 文章:cnzt-phtml
http://www.cnblogs.com/zt-blog/p/7762590.htmlnode
angular-cli (前提:nodejs npm)web
typescripttypescript
ng new my-ng2-app 建立一個新的名字爲my-ng2-app的骨架項目;數據庫
cd my-app 進入到項目目錄下npm
ng serve --open 啓動開發服務器並監聽文件變化,參數open打開瀏覽器並自動訪問http://localhost:4200/json
頁面及編譯後的文件以下:bootstrap
參考: https://angular.cn/tutorial/後端
Angular的指令有三種:結構性指令(如 ngSwitch、ngIf、ngFor等)、屬性型指令(ngClass、ngStyle、ngModel等)、自定義指令(如 組件component)api
首先,組件也是指令,是實現了模板特性的指令。
定義一個組件: (此處的OnInit爲生命週期鉤子函數,常在初始化組件數據時用到)
1. 引入組件方法 (import { Component, OnInit } from '@angular/core';)
2. @Component修飾器 (
@Component({})
export class AppComponent implements OnInit { .. }
)
3. 若是一個組件有輸入參數,那麼他還需引入@Input,以下:
import { Component, Input } from '@angular/core';
import { Hero } from './hero';
@Component({
selector: 'hero-detail',
template: ``,
})
export class HeroDetailComponent{
@Input() hero: Hero; // 經過 <hero-detail hero='selectedHero'> 傳值的
}
模塊分爲跟模塊和子模塊。
模塊包含了完成特定功能的一組組件。
定義一個模塊:
1. 引入NgModule (import { NgModule } from '@angular/core';)
2. 經過@NgModule定義模塊的元數據並處處模塊 (
@NgModule({
imports: [
BrowserModule,
FormsModule // 綁定 [(ngModel)]時須要此模塊
],
declarations: [ AppComponent, HeroDetailComponent ], // 生命此模塊包含的視圖:組件,指令,管道
bootstrap: [ AppComponent ]
})
export class AppModule { }
)
3. 一個新組的建件,須要import到相應的Module模塊中,並聲明到declarations:[]數組中。
Angualr的服務本質上師一個類,專一於作某件事情的類。實際應用中咱們一般用服務來獲取後臺數據、管理日誌、校驗數據等等。再經過依賴注入在組件中使用這些服務,而組件就應該保持精簡,雜事交給服務處理。
服務能夠註冊(providers:[XX,XX,...])在根模塊中,也能夠註冊在組件的元數據中。註冊在根模塊中表示全部地方使用同一個服務的實例,註冊在組件中表示每個新的組件實例都會有一個新的服務實例。
服務要素:
1. 定義一個服務
1.1 引入Injectable (import { Injectable } from '@angular/core';)
1.2 @Injectable修飾器 (
@Injectable()
export class HeroService{}
)
1.3 Promise處理異步
2. 在組件等中調用服務(依賴注入)
2.1 引入所需服務 (import { HeroService } from './hero.service';)
2.2 在服務提供商完成註冊 (providers: [HeroService ])
2.3 組件的構造函數中經過傳入一個私有變量完成依賴注入 (constructor(private heroService: HeroService){ 。。。 })
2.4 調用 this.heroService.XXX (this.heroService.getHeroes().then(。。。))
1. 基地址是必須的: <base href>組件,位於<head>區域內頂部。
2. 模塊文件中引入 import { RouterModule } from '@angular/router';
import元數據中定義:
RouterModule.forRoot([ //應用根部
{
path: 'heroes',
component: HeroesComponent
}
])
3. 路由組件中就能夠定義路由和路由模板了:
<a routerLink='/heroes'>Heroes</a> // 路由路徑
<router-outlet></router-outlet> // 路由模板/容器
4. 關於重定向:
{
path: '', // 給初始路徑重定向
redirectTo: '/dashboard',
pathMatch: 'full'
}
5.帶參數的路由:
5.1 路由器配置:
{
path: 'detail/:id',
component: HeroDetailComponent
}
5.2 組件中接收參數:
引入ActivatedRoute 和 ParamMap: ( import { ActivatedRoute, ParamMap } from '@angular/router'; );
將引入的服務依賴注入到constructor裏;
引入switchMap: import 'rxjs/add/operator/switchMap';
組件中接收參數的具體操做:
ngOnInit(): void{
this.route.paramMap
.switchMap((params: ParamMap) => this.heroService.getHero(+params.get('id')))
.subscribe(hero => this.hero=hero;)
}
導航方式1:模板中傳遞參數: <a *ngFor="let hero of heroes" [routerLink]="['/detail', hero.id]" class="col-1-4">
導航方式2:組件中調用: this.router.navigate(['/detail', this.selectedHero.id]);
將路由部分從新定義成一個新的模塊。典型路由模塊須要注意的有:
將路由抽出到一個變量中。若是你未來要導出這個模塊,這種 "路由模塊" 的模式也會更加明確。
添加RouterModule.forRoot(routes)
到imports
。
把RouterModule
添加到路由模塊的exports
中,以便關聯模塊(好比AppModule
)中的組件能夠訪問路由模塊中的聲明,好比RouterLink
和 RouterOutlet
。
無declarations
!聲明是關聯模塊的任務。
若是有守衛服務,把它們添加到本模塊的providers
中。
通常咱們用http服務獲取server數據,但在開發前期,也能夠利用InMemoryWebApi來實現本地模擬http測試接口。
本地模擬測試:
1. 引入相應模塊
import { HttpModule } from '@angular/http';
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InMemoryDataService } from './in-memory-data.service';
2. 模塊導入跟模塊中
imports: [
BrowserModule,
FormsModule,
HttpModule,
InMemoryWebApiModule.forRoot(InMemoryDataService),
AppRoutingModule
],
3. 定義一個產生本地(數據庫)數據的文件 : in-memory-data.service.ts :
import { InMemoryDbService } from 'angular-in-memory-web-api';
export class InMemoryDataService implements InMemoryDbService {
createDb() {
const heroes = [
{ id: 0, name: 'Zero' },
{ id: 11, name: 'Mr. Nice' },
{ id: 12, name: 'Narco' },
...
];
return {heroes};
}
}
4. 相應的service中應用http服務:
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise'; //將obervable可觀察對象轉換成Promise對象的操做符
@Injectable()
export class HeroService{
private heroesUrl = 'api/heroes';//這裏的heroes對應本地mock數據返回的那個字段
constructor(private http: Http){}
getHeroes(): Promise<Hero[]> { //stub樁方法
//如下爲模擬web-api方式實現
//InMemoryWebApiModule將Http客戶端默認的後端服務(這是一個輔助服務,負責與遠程服務器對話) 替換成了內存 Web API服務:
return this.http.get(this.heroesUrl) //http.get返回一個 RxJS 的Observable對象
.toPromise() //利用toPromise操做符把Observable直接轉換成Promise對象
.then(response => response.json().data as Hero[]) //調用 HTTP 的Reponse對象的json方法
.catch(this.handleError);
}
private handleError(error: any): Promise<any>{
console.error('An error occured', error); // for demo purposes only
return Promise.reject(error.message || error);
}
}
5. 以上就是基本的本地模擬http的實現步驟。
一個可觀察對象是一個事件流,能夠用數組型操做符處理它。
Angular內核提供了對可觀察對象的基本支持。咱們也能夠引入RxJS庫進行擴展,例如上面見到的http.get().toPromise()...就是利用toPromise操做符將http.get()返回的可觀察對象轉換成了Promise承諾。
*****那麼,既然咱們能夠用承諾Promise,爲啥開發中還會須要可觀察對象的方式呢?由於請求並不是老是「一次性」的,咱們開始一個請求並取消它,在server響應第一個求情以前再開始另外一個不一樣的請求。像這樣的 請求--取消--新請求 序列用 Promise是難以實現的,可是可觀察對象卻很容易實現。*****
------------------------------------------------------本小節待續------------------------------------------
1. 單元測試UT: karma (karma.conf.js)
2. 端到端測試e2e: protractor (protractor.conf.js)
Angular 的即時編譯(JiT)在瀏覽器中啓動並編譯全部的組件和模塊,動態運行應用程序。 它很適合在開發過程當中使用。可是在產品發佈時,推薦採用預編譯 (ahead-of-time) 模式。
參考: https://www.angular.cn/guide/quickstart