新手村第一步之搭建angular项目
首先,我们需要提前配置好node环境,以及npm。在这之后我们安装angular cli。
使用脚手架在终端搭建一个angular项目:
ng new angular-tour-of-heroes
进行一些选项,我们这里使用Scss,进入到项目文件后
接着使用命令 ng serve --open
启动服务。
现在我们就可以开始英雄之旅了:
新手村第二步之创建英雄列表组件
首先利用ng generate component heroes
快速为app创建一个子组件,于是我们可以看到有四个文件
添加 hero 属性 hero = 'Windstorm';
显示heroes组件视图
真实的英雄当然不止一个名字,我们还可以添加一个类。
先在app中创建一个Hero.ts文件,写入
export interface Hero {
id: number,
name: string
}
第二步,在heroes.component.ts
中引入
import { Hero } from '../hero';
第三步,更改ts中的代码
hero: Hero = {
id: 1,
name: 'Windstorm'
}
此刻页面会显示
显然是不正确的。我们需要更改hero对象的显示。
<p>{{hero.id}}</p>
<p>{{hero.name}}</p>
此外还可以使用 UppercasePipe 进行格式化
<p>{{hero.id}}</p>
<p>{{hero.name | uppercase}}</p>
浏览器刷新了。现在,英雄的名字显示成了大写字母。
绑定表达式中的 uppercase
位于管道操作符 | 后面,用来调用内置管道 UppercasePipe
。
管道 是格式化字符串、金额、日期和其它显示数据的好办法。Angular
发布了一些内置管道,而且你还可以创建自己的管道。
ngModel 双向数据绑定
打开 app.module.ts
并从 @angular/forms
库中导入 FormsModule
符号。
import { FormsModule } from '@angular/forms'; // <-- NgModel lives here
然后把 FormsModule
添加到 @NgModule
的 imports
数组中,这里是该应用所需外部模块的列表。
imports: [
BrowserModule,
FormsModule
],
在hero的html里
<p>{{hero.id}}</p>
<p>{{hero.name | uppercase}}</p>
<div>
<label for="name"> Hero name: </label>
<input id="name" [(ngModel)]="hero.name" placeholder="name">
</div>
这便是经典的数据驱动视图。
显示英雄列表
第一步是创建一些要显示的英雄。
在 src/app/
目录下创建一个名叫 mock-heroes.ts
的文件。定义一个包含十个英雄的常量数组 HEROES
,并导出它。该文件是这样的。
import { Hero } from './hero';
export const HEROES: Hero[] = [
{ id: 12, name: 'Dr. Nice' },
{ id: 13, name: 'Bombasto' },
{ id: 14, name: 'Celeritas' },
{ id: 15, name: 'Magneta' },
{ id: 16, name: 'RubberMan' },
{ id: 17, name: 'Dynama' },
{ id: 18, name: 'Dr. IQ' },
{ id: 19, name: 'Magma' },
{ id: 20, name: 'Tornado' }
];
ts:
import { Component } from '@angular/core';
import { Hero } from '../hero';
import { HEROES } from '../mock-heroes';
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent {
heroes = HEROES;
selectedHero?: Hero;
onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
html:
<h2>My Heroes</h2>
<ul class="heroes">
<li *ngFor="let hero of heroes">
<button [class.selected]="hero === selectedHero" type="button" (click)="onSelect(hero)">
<span class="badge">{{hero.id}}</span>
<span class="name">{{hero.name}}</span>
</button>
</li>
</ul>
<div *ngIf="selectedHero">
<h2>{{selectedHero.name | uppercase}} Details</h2>
<div>id: {{selectedHero.id}}</div>
<div>
<label for="hero-name">Hero name: </label>
<input id="hero-name" [(ngModel)]="selectedHero.name" placeholder="name">
</div>
</div>
进阶-组件化开发
对于当前的页面效果,同时显示了英雄列表和所选英雄的详情。但是把所有特性都放在同一个组件中,将会使应用“长大”后变得不可维护。你要把大型组件拆分成小一点的子组件,每个子组件都要集中精力处理某个特定的任务或工作流。
接下来,我们开始组件化开发的步骤:
首先用指令创建一个新的组件,ng generate component hero-detail
然后我们先去修改它的html部分,将原来的展示部分全部迁移到新组件中,并将原组件代码补充
<app-hero-detail [hero]="selectedHero"></app-hero-detail>
这样,新旧组件之间就会形成父子关系的组件,由于hero
的位置发生了改变,我们不得不添加 @Input() hero 属性,使其生效。
HeroDetailComponent
模板中绑定了组件中的 hero
属性,它的类型是 Hero
。
打开 HeroDetailComponent
类文件,并导入 Hero
符号。
@Input() hero?: Hero;
这就是你要对 HeroDetailComponent
类做的唯一一项修改。没有其它属性,也没有展示逻辑。这个组件所做的只是通过 hero
属性接收一个英雄对象,并显示它。
服务
当前我们使用的是假数据,但在实际开发的过程是需要从任何地方获取数据,比如:Web 服务、本地存储(LocalStorage)或一个模拟的数据源。针对数据来说,我们不应该依托于组件,而是将数据访问的职责委托给某个服务。
依然是ng generate service hero
指令来创建一个服务,引入数据与类
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
再写一个方法用于返回数据。
getHeroes(): Hero[] {
return HEROES;
}
接着,我们将服务在组件中引入,注意 我们在引入之后还需在constructor
也就是构造函数中注入。
constructor(private heroService: HeroService) {}
然后再写一个函数用于接受服务返回的数据。
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
并且在生命周期中调用它。
使用Observable
优化
引入服务 import { Observable, of } from 'rxjs';
getHeroes(): Observable<Hero[]> {
const heroes = of(HEROES);
return heroes;
}