把获取模型数据的任务重构为一个单独的服务,它将提供英雄数据,并把服务在所有需要英雄数据的组件间共享。
@Injectable()
export class HeroService {
getHeroes(): void {} // stub
}
HeroService
可以从任何地方获取Hero
数据 —— Web服务、本地存储或模拟数据源。
Service不是new()出来的
文档里给出了李菊福的理由:
我们的组件得弄清楚该如何创建
HeroService
。 如果有一天我们修改了HeroService
的构造函数,我们不得不找出创建过此服务的每一处代码,并修改它。 围着补丁代码转圈很容易导致错误,还会增加测试负担。我们每次使用
new
都会创建一个新的服务实例。 如果这个服务需要缓存英雄列表,并把这个缓存共享给别人呢?怎么办? 没办法,做不到。我们把
AppComponent
锁定到HeroService
的一个特定实现。 我们很难在不同的场景中切换实现。 例如,能离线操作吗?能在测试时使用不同的模拟版本吗?这可不容易。
在app.component.ts里
import { Component, OnInit } from '@angular/core'; import { Hero } from './hero';
import { HeroService } from './hero.service'; @Component({
selector: 'my-app',
template: `...‘,//略
providers: [HeroService]
})
export class AppComponent implements OnInit {
title = 'Tour of Heroes';
heroes: Hero[];
selectedHero: Hero; constructor(private heroService: HeroService) { } getHeroes(): void {
this.heroService.getHeroes().then(heroes => this.heroes = heroes);
} ngOnInit(): void {
this.getHeroes();
} onSelect(hero: Hero): void {
this.selectedHero = hero;
}
}
1 import
2 在@Component里增加 providers: [HeroService]
3 在APPComponent的构造函数里传入constructor(private heroService: HeroService),这样直接有了heroService的私有属性,不需要在开头声明了
括号里这句,是简写的箭头函数。
只有1个参数的,可以省略();
只有1行函数体,可以省略{}
heroes => this.heroes = heroes (heroes) => {this.heroes = heroes}
异步服务
Promise对象类似 waitable object
getHeroes(): Promise<Hero[]> {
return Promise.resolve(HEROES);
}
使用模拟数据。我们通过返回一个 立即解决的承诺 的方式,模拟了一个超快、零延迟的超级服务器。
this.heroes
会被赋值为一个Promise
而不再是英雄数组。
Model部分
类似 models.py 定义数据类型
export class Hero {
id: number;
name: string;
}
类似 models.py定义的ORM类。可以送进模板用双括号访问属性 {{hero.name}}
ng的双向绑定很给力。
<div>
<label>name: </label>
<input [(ngModel)]="hero.name" placeholder="name">
</div>