目录
- 第一节 - Angular 简介
- 第二节 - Angular 环境搭建
- 第三节 - 插值表达式
- 第四节 - 自定义组件
- 第五节 - 常用指令简介
- 第六节 - 事件绑定
- 第七节 - 表单模块简介
- 第八节 - Http 模块简介
- 第九节 - 注入服务
- 第十节 - 路由模块简介
第一节 Angular 简介
Angular 是什么
Angular 有什么特点
- 基于 Angular 我们可以构建适用于所有平台的应用。比如:Web 应用、移动 Web 应用、移动应用和桌面应用等。
- 通过 Web Worker和服务端渲染 (SSR),达到在如今Web平台上所能达到的最高渲染速度。
- Angular 让你能够有效掌控可伸缩性。基于 RxJS、Immutable.js 和其它推送模型,能适应海量数据需求。
Angular 提供了哪些功能
- 动态HTML
- 强大的表单系统 (模板驱动和模型驱动)
- 强大的视图引擎
- 事件处理
- 快速的页面渲染
- 灵活的路由
- HTTP 服务
- 视图封装
- AOT、Tree Shaking
Angular 与 AngularJS 有什么区别
- 不再有
Controller
和Scope
- 更好的组件化及代码复用
- 降低了学习曲线
- 更好的移动端支持
- 引入了
RxJS
与Observable
- 引入了
Zone.js
,提供更加智能的变化检测
第二节 - Angular 环境搭建
基础要求
Angular 开发环境配置方式
- 基于 Angular Quickstart
- 基于 Angular CLI
- npm install -g @angular/cli
配置开发环境
本快速入门教程,选用第一种配置方式搭建 Angular 开发环境:
- 使用
Git
克隆 quickstart 项目
git clone ng4-quickstart
- 使用
IDE
打开已新建的项目 (本教程使用的 IDE 是 )
code ./ng4-quickstart
- 安装项目所需依赖
npm i
- 验证环境是否搭建成功
npm start
第三节 - 插值表达式
在 Angular 中,我们可以使用 {{}}
插值语法实现数据绑定。
绑定普通文本
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>我来自<strong>{{address.province}}</strong>省,
<strong>{{address.city}}</strong>市
</p>
`,
})
export class AppComponent {
name = 'Semlinker';
address = {
province: '福建',
city: '厦门'
}
}
值得一提的是,我们可以使用 Angular 内置的 json
管道,来显示对象信息:
@Component({
selector: 'my-app',
template: `
...
<p>{{address | json}}</p>
`,
})
export class AppComponent {
name = 'Semlinker';
address = {
province: '福建',
city: '厦门'
}
}
第四节 - 自定义组件
在 Angular 中,我们可以通过 Component
装饰器和自定义组件类来创建自定义组件。
基础知识
定义组件的元信息
在 Angular 中,我们可以使用 Component
装饰器来定义组件的元信息:
@Component({
selector: 'my-app', // 用于定义组件在HTML代码中匹配的标签
template: `<h1>Hello {{name}}</h1>`, // 定义组件内嵌视图
})
定义组件类
export class AppComponent {
name = 'Angular';
}
定义数据接口
在 TypeScript 中的接口是一个非常灵活的概念,除了可用于对类的一部分行为进行抽象以外,也常用于对「对象的形状(Shape)」进行描述。
interface Person {
name: string;
age: number;
}
let semlinker: Person = {
name: 'semlinker',
age: 31
};
自定义组件示例
创建 UserComponent 组件
import { Component } from '@angular/core';
@Component({
selector: 'sl-user',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我来自<strong>{{address.province}}</strong>省,
<strong>{{address.city}}</strong>市
</p>
`
})
export class UserComponent {
name = 'Semlinker';
address = {
province: '福建',
city: '厦门'
};
}
声明 UserComponent 组件
// ...
import { UserComponent } from
@NgModule({
imports: [ BrowserModule ],
declarations: [ AppComponent, UserComponent],
bootstrap: [ AppComponent ]
})
export class AppModule { }
使用 UserComponent 组件
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: '厦门'
}
}
}
接口使用示例
定义 Address 接口
interface Address {
province: string;
city: string;
}
使用 Address 接口
export class UserComponent {
name: string;
address: Address;
// ...
}
第五节 - 常用指令简介
在 Angular 实际项目中,最常用的指令是 ngIf
和 ngFor
指令。
基础知识
ngIf 指令简介
该指令用于根据表达式的值,动态控制模板内容的显示与隐藏。它与 AngularJS 1.x 中的 ng-if
指令的功能是等价的。
ngIf 指令语法
<div *ngIf="condition">...</div>
ngFor 指令简介
该指令用于基于可迭代对象中的每一项创建相应的模板。它与 AngularJS 1.x 中的 ng-repeat
指令的功能是等价的。
ngFor 指令语法
<li *ngFor="let item of items;">...</li>
ngIf 与 ngFor 指令使用示例
import { Component } from '@angular/core';
interface Address {
province: string;
city: string;
}
@Component({
selector: 'sl-user',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我来自<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: '厦门'
};
this.showSkills = true;
this.skills = ['AngularJS 1.x', 'Angular 2.x', 'Angular 4.x'];
}
}
第六节 - 事件绑定
在 Angular 中,我们可以通过 (eventName)
的语法,实现事件绑定。
基础知识
事件绑定语法
<date-picker (dateChanged)="statement()"></date-picker>
等价于
<date-picker on-dateChanged="statement()"></date-picker>
介绍完事件绑定的语法,接下来我们来为第五节中的 UserComponent
组件,开发一个功能,即可以让用户动态控制技能信息的显示与隐藏。
事件绑定示例
@Component({
selector: 'sl-user',
template: `
...
<button (click)="toggleSkills()">
{{ showSkills ? "隐藏技能" : "显示技能" }}
</button>
...
`
})
export class UserComponent {
// ...
toggleSkills() {
this.showSkills = !this.showSkills;
}
}
第七节 - 表单模块简介
Angular 中有两种表单:
- Template Driven Forms - 模板驱动式表单 (类似于 AngularJS 1.x 中的表单 )
- Reactive Forms - 响应式表单
本小节主要介绍模板驱动式的表单,接下来我们来演示如何通过表单来为我们的之前创建的 UserComponent
组件,增加让用户自定义技能的功能。
基础知识
导入表单模块
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>
等价于
<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);
}
}
}
第八节 - Http 模块简介
基础知识
导入 Http 模块
// ...
import { HttpModule } from '@angular/http';
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule],
declarations: [AppComponent, UserComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
使用 Http 服务步骤
(2) 导入 RxJS 中的 map
操作符
(5) 调用 Response 对象的 json()
方法,把响应体转成 JSON 对象
(6) 把请求的结果,赋值给对应的属性
Http 服务使用示例
使用 Http 服务
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() {
// (4)
.map(res => res.json()) // (5)
.subscribe(data => {
if (data) this.members = data; // (6)
});
}
}
声明 MembersComponent 组件
// ...
import { MembersComponent } from
@NgModule({
imports: [BrowserModule, FormsModule, HttpModule],
declarations: [AppComponent, UserComponent, MembersComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
使用 MembersComponent 组件
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<sl-members></sl-members>
`,
})
export class AppComponent {}
第九节 - 注入服务
基础知识
组件中注入服务步骤
(1) 配置已创建的服务,如:
@NgModule({
// ...
providers: [MemberService]
})
export class AppModule { }
(2) 导入已创建的服务,如:
import { MemberService } from '../member.service';
(3) 使用构造注入方式,注入服务:
export class MembersComponent implements OnInit {
// ...
constructor(private memberService: MemberService) { }
}
服务使用示例
创建 MemberService 服务
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class MemberService {
constructor(private http: Http) { }
getMembers() {
return this.http
.map(res => res.json())
}
}
配置 MemberService 服务
import { MemberService } from "./member.service";
@NgModule({
// ...
providers:[MemberService],
bootstrap: [AppComponent]
})
export class AppModule { }
使用 MemberService 服务
// ...
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
export const ROUTES: Routes = [
{ path: 'user', component: UserComponent }
];
@NgModule({
imports: [
BrowserModule,
RouterModule.forRoot(ROUTES)
],
// ...
})
export class AppModule {}
routerLink 指令
为了让我们链接到已设置的路由,我们需要使用 routerLink 指令,具体示例如下:
<nav>
<a routerLink="/">首页</a>
<a routerLink="/user">我的</a>
</nav>
当我们点击以上的任意链接时,页面不会被重新加载。反之,我们的路径将在 URL 地址栏中显示,随后进行后续视图更新,以匹配 routerLink
中设置的值。
router-outlet 指令
该指令用于告诉 Angular 在哪里加载组件,当 Angular 路由匹配到响应路径,并成功找到需要加载的组件时,它将动态创建对应的组件,并将其作为兄弟元素,插入到 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>欢迎来到Angular的世界</h1>
<nav>
<a routerLink="/user">我的</a>
<a routerLink="/members">Angular成员</a>
</nav>
<router-outlet></router-outlet>
</div>
`,
})
export class AppComponent { }
完整示例
AppModule
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
import { UserComponent } from
import { MembersComponent } from
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 { }
AppComponent
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
template: `
<div class="app">
<h1>欢迎来到Angular的世界</h1>
<nav>
<a routerLink="/user">我的</a>
<a routerLink="/members">Angular成员</a>
</nav>
<router-outlet></router-outlet>
</div>
`,
})
export class AppComponent { }
UserComponent
import { Component } from '@angular/core';
interface Address {
province: string;
city: string;
}
@Component({
selector: 'sl-user',
template: `
<h2>大家好,我是{{name}}</h2>
<p>我来自<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: '厦门'
};
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);
}
}
}
MembersComponent
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;
});
}
}
MemberService
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class MemberService {
constructor(private http: Http) { }
getMembers() {
return this.http
.map(res => res.json())
}
}
我有话说
除了本系列教程外,还有其它学习资源么?
本系列教程的主要目的是让初学者对 Angular 的相关基础知识,有一定的了解。除了本系列教程外,初学者还可以参考以下教程: