Angular 是由谷歌開(kāi)發(fā)與維護(hù)一個(gè)開(kāi)發(fā)跨平臺(tái)應(yīng)用程序的框架,同時(shí)適用于手機(jī)與桌面。
Controller
和 Scope
RxJS
與 Observable
Zone.js
,提供更加智能的變化檢測(cè)本快速入門(mén)教程,選用第一種配置方式搭建 Angular 開(kāi)發(fā)環(huán)境:
Git
克隆 quickstart 項(xiàng)目
git clone https://github.com/angular/quickstart ng4-quickstart
IDE
打開(kāi)已新建的項(xiàng)目 (本教程使用的 IDE 是 Visual Studio Code)
code ./ng4-quickstart
npm i
npm start
在 Angular 中,我們可以使用 {{}}
插值語(yǔ)法實(shí)現(xiàn)數(shù)據(jù)綁定。
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `<h1>Hello {{name}}</h1>`,
})
export class AppComponent {
name = 'Angular';
}
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我來(lái)自<strong>{{address.province}}</strong>省,
<strong>{{address.city}}</strong>市
</p>
`,
})
export class AppComponent {
name = 'Semlinker';
address = {
province: '福建',
city: '廈門(mén)'
}
}
值得一提的是,我們可以使用 Angular 內(nèi)置的 json
管道,來(lái)顯示對(duì)象信息:
@Component({
selector: 'my-app',
template: `
...
<p>{{address | json}}</p>
`,
})
export class AppComponent {
name = 'Semlinker';
address = {
province: '福建',
city: '廈門(mén)'
}
}
在 Angular 中,我們可以通過(guò) Component
裝飾器和自定義組件類(lèi)來(lái)創(chuàng)建自定義組件。
在 Angular 中,我們可以使用 Component
裝飾器來(lái)定義組件的元信息:
@Component({
selector: 'my-app', // 用于定義組件在HTML代碼中匹配的標(biāo)簽
template: `<h1>Hello {{name}}</h1>`, // 定義組件內(nèi)嵌視圖
})
export class AppComponent {
name = 'Angular';
}
在 TypeScript 中的接口是一個(gè)非常靈活的概念,除了可用于對(duì)類(lèi)的一部分行為進(jìn)行抽象以外,也常用于對(duì)「對(duì)象的形狀(Shape)」進(jìn)行描述。
interface Person {
name: string;
age: number;
}
let semlinker: Person = {
name: 'semlinker',
age: 31
};
import { Component } from '@angular/core';
@Component({
selector: 'sl-user',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我來(lái)自<strong>{{address.province}}</strong>省,
<strong>{{address.city}}</strong>市
</p>
`
})
export class UserComponent {
name = 'Semlinker';
address = {
province: '福建',
city: '廈門(mén)'
};
}
// ...
import { UserComponent } from './user.component';
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, UserComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<sl-user></sl-user>
`,
})
export class AppComponent {}
@Component({...})
export class UserComponent {
name: string;
address: any;
constructor() {
this.name = 'Semlinker';
this.address = {
province: '福建',
city: '廈門(mén)'
}
}
}
interface Address {
province: string;
city: string;
}
export class UserComponent {
name: string;
address: Address;
// ...
}
在 Angular 實(shí)際項(xiàng)目中,最常用的指令是 ngIf
和 ngFor
指令。
該指令用于根據(jù)表達(dá)式的值,動(dòng)態(tài)控制模板內(nèi)容的顯示與隱藏。它與 AngularJS 1.x 中的 ng-if
指令的功能是等價(jià)的。
<div *ngIf="condition">...</div>
該指令用于基于可迭代對(duì)象中的每一項(xiàng)創(chuàng)建相應(yīng)的模板。它與 AngularJS 1.x 中的 ng-repeat
指令的功能是等價(jià)的。
<li *ngFor="let item of items;">...</li>
import { Component } from '@angular/core';
interface Address {
province: string;
city: string;
}
@Component({
selector: 'sl-user',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我來(lái)自<strong>{{address.province}}</strong>省,
<strong>{{address.city}}</strong>市
</p>
<div *ngIf="showSkills">
<h3>我的技能</h3>
<ul>
<li *ngFor="let skill of skills">
{{skill}}
</li>
</ul>
</div>
`
})
export class UserComponent {
name: string;
address: Address;
showSkills: boolean;
skills: string[];
constructor() {
this.name = 'Semlinker';
this.address = {
province: '福建',
city: '廈門(mén)'
};
this.showSkills = true;
this.skills = ['AngularJS 1.x', 'Angular 2.x', 'Angular 4.x'];
}
}
在 Angular 中,我們可以通過(guò) (eventName)
的語(yǔ)法,實(shí)現(xiàn)事件綁定。
<date-picker (dateChanged)="statement()"></date-picker>
等價(jià)于
<date-picker on-dateChanged="statement()"></date-picker>
介紹完事件綁定的語(yǔ)法,接下來(lái)我們來(lái)為第五節(jié)中的 UserComponent
組件,開(kāi)發(fā)一個(gè)功能,即可以讓用戶(hù)動(dòng)態(tài)控制技能信息的顯示與隱藏。
@Component({
selector: 'sl-user',
template: `
...
<button (click)="toggleSkills()">
{{ showSkills ? "隱藏技能" : "顯示技能" }}
</button>
...
`
})
export class UserComponent {
// ...
toggleSkills() {
this.showSkills = !this.showSkills;
}
}
Angular 中有兩種表單:
本小節(jié)主要介紹模板驅(qū)動(dòng)式的表單,接下來(lái)我們來(lái)演示如何通過(guò)表單來(lái)為我們的之前創(chuàng)建的 UserComponent
組件,增加讓用戶(hù)自定義技能的功能。
import { FormsModule } from '@angular/forms';
// ...
@NgModule({
imports: [BrowserModule, FormsModule],
declarations: [AppComponent, UserComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
<video #player></video>
<button (click)="player.pause()">Pause</button>
等價(jià)于
<video ref-player></video>
@Component({
selector: 'sl-user',
template: `
...
<div *ngIf="showSkills">
<h3>我的技能</h3>
...
<form (submit)="addSkill(skill.value)">
<label>添加技能</label>
<input type="text" #skill>
</form>
</div>
`
})
export class UserComponent {
// ...
addSkill(skill: string) {
let skillStr = skill.trim();
if (this.skills.indexOf(skillStr) === -1) {
this.skills.push(skillStr);
}
}
}
// ...
import { HttpModule } from '@angular/http';
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule],
declarations: [AppComponent, UserComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
(1) 從 @angular/http
模塊中導(dǎo)入 Http 類(lèi)
(2) 導(dǎo)入 RxJS 中的 map
操作符
(3) 使用 DI 方式注入 http 服務(wù)
(4) 調(diào)用 http 服務(wù)的 get()
方法,設(shè)置請(qǐng)求地址并發(fā)送 HTTP 請(qǐng)求
(5) 調(diào)用 Response 對(duì)象的 json()
方法,把響應(yīng)體轉(zhuǎn)成 JSON 對(duì)象
(6) 把請(qǐng)求的結(jié)果,賦值給對(duì)應(yīng)的屬性
import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http'; // (1)
import 'rxjs/add/operator/map'; // (2)
interface Member {
id: string;
login: string;
avatar_url: string;
}
@Component({
selector: 'sl-members',
template: `
<h3>Angular Orgs Members</h3>
<ul *ngIf="members">
<li *ngFor="let member of members;">
<p>
<img [src]="member.avatar_url" width="48" height="48"/>
ID:<span>{{member.id}}</span>
Name: <span>{{member.login}}</span>
</p>
</li>
</ul>
`
})
export class MembersComponent implements OnInit {
members: Member[];
constructor(private http: Http) { } // (3)
ngOnInit() {
this.http.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`) // (4)
.map(res => res.json()) // (5)
.subscribe(data => {
if (data) this.members = data; // (6)
});
}
}
// ...
import { MembersComponent } from './members.component';
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule],
declarations: [AppComponent, UserComponent, MembersComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<sl-members></sl-members>
`,
})
export class AppComponent {}
(1) 配置已創(chuàng)建的服務(wù),如:
@NgModule({
// ...
providers: [MemberService]
})
export class AppModule { }
(2) 導(dǎo)入已創(chuàng)建的服務(wù),如:
import { MemberService } from '../member.service';
(3) 使用構(gòu)造注入方式,注入服務(wù):
export class MembersComponent implements OnInit {
// ...
constructor(private memberService: MemberService) { }
}
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class MemberService {
constructor(private http: Http) { }
getMembers() {
return this.http
.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`)
.map(res => res.json())
}
}
import { MemberService } from "./member.service";
@NgModule({
// ...
providers:[MemberService],
bootstrap: [AppComponent]
})
export class AppModule { }
// ...
import { MemberService } from "./member.service";
@Component({...})
export class MembersComponent implements OnInit {
members: Member[];
constructor(private memberService: MemberService) { }
ngOnInit() {
this.memberService.getMembers()
.subscribe(data => {
if (data) this.members = data;
});
}
}
// ...
import { RouterModule } from '@angular/router';
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule, RouterModule],
declarations: [AppComponent, UserComponent, MembersComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Routes, RouterModule } from '@angular/router';
import { UserComponent } from './user.component';
export const ROUTES: Routes = [
{ path: 'user', component: UserComponent }
];
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES)
],
// ...
})
export class AppModule {}
為了讓我們鏈接到已設(shè)置的路由,我們需要使用 routerLink 指令,具體示例如下:
<nav>
<a routerLink="/">首頁(yè)</a>
<a routerLink="/user">我的</a>
</nav>
當(dāng)我們點(diǎn)擊以上的任意鏈接時(shí),頁(yè)面不會(huì)被重新加載。反之,我們的路徑將在 URL 地址欄中顯示,隨后進(jìn)行后續(xù)視圖更新,以匹配 routerLink
中設(shè)置的值。
該指令用于告訴 Angular 在哪里加載組件,當(dāng) Angular 路由匹配到響應(yīng)路徑,并成功找到需要加載的組件時(shí),它將動(dòng)態(tài)創(chuàng)建對(duì)應(yīng)的組件,并將其作為兄弟元素,插入到 router-outlet
元素中。具體示例如下:
@Component({
selector: 'app-root',
template: `
<div class="app">
<h3>Our app</h3>
<router-outlet></router-outlet>
</div>
`
})
export class AppComponent {}
export const ROUTES: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'user' },
{ path: 'user', component: UserComponent },
{ path: 'members', component: MembersComponent }
];
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule,
RouterModule.forRoot(ROUTES)],
// ...
})
export class AppModule { }
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div class="app">
<h1>歡迎來(lái)到Angular的世界</h1>
<nav>
<a routerLink="/user">我的</a>
<a routerLink="/members">Angular成員</a>
</nav>
<router-outlet></router-outlet>
</div>
`,
})
export class AppComponent { }
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { RouterModule, Routes } from '@angular/router';
import { AppComponent } from './app.component';
import { UserComponent } from './user.component';
import { MembersComponent } from './members.component';
import { MemberService } from "./member.service";
export const ROUTES: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'user' },
{ path: 'user', component: UserComponent },
{ path: 'members', component: MembersComponent }
];
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule,
RouterModule.forRoot(ROUTES)],
declarations: [AppComponent, UserComponent, MembersComponent],
providers: [MemberService],
bootstrap: [AppComponent]
})
export class AppModule { }
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div class="app">
<h1>歡迎來(lái)到Angular的世界</h1>
<nav>
<a routerLink="/user">我的</a>
<a routerLink="/members">Angular成員</a>
</nav>
<router-outlet></router-outlet>
</div>
`,
})
export class AppComponent { }
import { Component } from '@angular/core';
interface Address {
province: string;
city: string;
}
@Component({
selector: 'sl-user',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我來(lái)自<strong>{{address.province}}</strong>省,
<strong>{{address.city}}</strong>市
</p>
<button (click)="toggleSkills()">
{{ showSkills ? "隱藏技能" : "顯示技能" }}
</button>
<div *ngIf="showSkills">
<h3>我的技能</h3>
<ul>
<li *ngFor="let skill of skills">
{{skill}}
</li>
</ul>
<form (submit)="addSkill(skill.value)">
<label>添加技能</label>
<input type="text" #skill>
</form>
</div>
`
})
export class UserComponent {
name: string;
address: Address;
showSkills: boolean;
skills: string[];
constructor() {
this.name = 'Semlinker';
this.address = {
province: '福建',
city: '廈門(mén)'
};
this.showSkills = true;
this.skills = ['AngularJS 1.x', 'Angular 2.x', 'Angular 4.x'];
}
toggleSkills() {
this.showSkills = !this.showSkills;
}
addSkill(skill: string) {
let skillStr = skill.trim();
if (this.skills.indexOf(skillStr) === -1) {
this.skills.push(skillStr);
}
}
}
import { Component, OnInit } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import { MemberService } from "./member.service";
interface Member {
id: string;
login: string;
avatar_url: string;
}
@Component({
selector: 'sl-members',
template: `
<h3>Angular Orgs Members</h3>
<ul *ngIf="members">
<li *ngFor="let member of members;">
<p>
<img [src]="member.avatar_url" width="48" height="48"/>
ID:<span>{{member.id}}</span>
Name: <span>{{member.login}}</span>
</p>
</li>
</ul>
`
})
export class MembersComponent implements OnInit {
members: Member[];
constructor(private memberService: MemberService) { }
ngOnInit() {
this.memberService.getMembers()
.subscribe(data => {
if (data) this.members = data;
});
}
}
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class MemberService {
constructor(private http: Http) { }
getMembers() {
return this.http
.get(`https://api.github.com/orgs/angular/members?page=1&per_page=5`)
.map(res => res.json())
}
}
本系列教程的主要目的是讓初學(xué)者對(duì) Angular 的相關(guān)基礎(chǔ)知識(shí),有一定的了解。除了本系列教程外,初學(xué)者還可以參考以下教程:
更多建議: