在多个组件中我们需要使用hero的数据,在生产环境下,这些数据或许是从网络服务器端获取,或许是本地静态数据,然而我们又不想copy到这个组件,copy到那个组件中。我们可以创建一个唯一的可重复使用的请求数据的组件。Angular2.0中将使用注入的方式给组件注入service组件。
service 组件命名规范
在app目录下新建一个文件hero.service.ts,内容如下:
import {Injectable} from '@angular/core';
@Injectable()
export class HeroService {
getHeroes() {
}
}
上面导入了Injectable
组件,并且在HeroService
添加了@Injectable()
注解。提供了一个获取hero data的接口。 对于HeroService
的hero data
可以是服务器端HTTP请求获取,也可以是本地静态数据。
创建一个模拟数据mock-heroes.ts
文件,把前面AppComponent中的Hero数据copy到这里,内容如下:
import {Hero} from './hero';
export var HEROES: Hero[] = [
{ "id": 11, "name": "奥巴马" },
{ "id": 12, "name": "希维尔" },
{ "id": 13, "name": "兰博" },
{ "id": 14, "name": "雷克顿" },
{ "id": 15, "name": "提莫" },
{ "id": 16, "name": "德芙兰" },
{ "id": 17, "name": "德玛" },
{ "id": 18, "name": "波比" },
{ "id": 19, "name": "布兰德" },
{ "id": 20, "name": "卡尔" }
];
导出的HEROES
可以在其他组件中使用,例如在HeroService
中使用:
import {HEROES} from './mock-heroes';
import {Injectable} from '@angular/core';
@Injectable()
export class HeroService {
getHeroes() {
return HEROES;
}
}
在Angular中使用constructor定义私有变量,constructor中的变量一般前面带_
表示是要注入的变量
constructor(private _heroService: HeroService) { }
在@Component
中通过provider
属性注册HeroService
providers: [HeroService]
在组件树中也可以使用父组件的provider中的Service。
在AppComponent
中添加getHero
方法。
getHeroes() {
this.heroes = this._heroService.getHeroes();
}
上面在AppComponent
组件中定义的getHeroes我们在哪儿调用呢 ,可能会想到在组件初始化的时候调用。
Angular提供了ngOnInit
方法,ngOnInit
是在组件初始化的时候,由Angular内部系统自动调用,我们可以在组件初始化的时候加入我们自己的业务代码,比如获取组件template
中需要的数据,ngOnInit
方法是组件生命周期的钩子函数。所以可以在ngOnInit
中调用getHeroes
。
import {OnInit} from '@angular/core';
export class AppComponent implements OnInit {
ngOnInit() {
getHeroes() ;
}
}
在HeroService
中getHeroes()
函数内,获取数据有时候是从服务器端Http获取,有时候是本地立即能返回的数据, 为了在加载Angular组件时,获取数据不受Http请求延时的影响,我们需要使用声明获取数据是同步(Promises
)还是异步
Promises
是CommonJS
规范中提出的,所谓Promise
,字面上可以理解为“承诺”,就是说A调用B,B返回一个“承诺”给A,然后A就可以在写计划的时候这么写:当B返回结果给我的时候,A执行方案S1,反之如果B因为什么原因没有给到A想要的结果,那么A执行应急方案S2,这样一来,所有的潜在风险都在A的可控范围之内了。
上面这句话,翻译成代码类似:
var resB = B();
var runA = function() {
resB.then(
function(object) {
.....
},
function(error) {
......
}
);
};
runA();
更多关于Promise的资料
在HeroService
中使用Promises
getHeroes() {
return Promise.resolve(HEROES);
}
使用Promise
中的then
回调函数,then
函数带一个参数data。
getHeroes() {
this._heroService.getHeroes().then(heroes => this.heroes = heroes);
}
getHeroes中
的then回调函数只写了success
时候的方法,没有对error
进行处理。并且在success
处理中使用了箭头函数。
箭头函数是ES6的新规范。箭头函数简单的说就是:=>
前面是函数的参数,=>
后面的内容是回调函数then()的函数体。
关于箭头函数的相关在知识 大家可以百度一下,这里收集了几篇
hero.service.ts
import {Hero} from './hero';
import {HEROES} from './mock-heroes';
import {Injectable} from '@angular/core';
@Injectable()
export class HeroService {
getHeroes() {
return Promise.resolve(HEROES);
}
// 模拟延迟请求
getHeroesSlowly() {
return new Promise<Hero[]>(resolve =>
setTimeout(()=>resolve(HEROES), 2000) // 2 seconds
);
}
}
app.component.ts
import {Component, OnInit} from '@angular/core';
import {Hero} from './hero';
import {HeroDetailComponent} from './hero-detail.component';
import {HeroService} from './hero.service';
@Component({
selector: 'my-app',
template:`
{{title}}
My Heroes
-
{{hero.id}} {{hero.name}}
`,
styles:[`
.selected {
background-color: #CFD8DC !important;
color: white;
}
.heroes {
margin: 0 0 2em 0;
list-style-type: none;
padding: 0;
width: 10em;
}
.heroes li {
cursor: pointer;
position: relative;
left: 0;
background-color: #EEE;
margin: .5em;
padding: .3em 0em;
height: 1.6em;
border-radius: 4px;
}
.heroes li.selected:hover {
color: white;
}
.heroes li:hover {
color: #607D8B;
background-color: #EEE;
left: .1em;
}
.heroes .text {
position: relative;
top: -3px;
}
.heroes .badge {
display: inline-block;
font-size: small;
color: white;
padding: 0.8em 0.7em 0em 0.7em;
background-color: #607D8B;
line-height: 1em;
position: relative;
left: -1px;
top: -4px;
height: 1.8em;
margin-right: .8em;
border-radius: 4px 0px 0px 4px;
}
`],
directives: [HeroDetailComponent],
providers: [HeroService]
})
export class AppComponent implements OnInit {
public title = 'Tour of Heroes';
public heroes: Hero[];
public selectedHero: Hero;
constructor(private _heroService: HeroService) { }
getHeroes() {
this._heroService.getHeroes().then(heroes => this.heroes = heroes);
}
ngOnInit() {
this.getHeroes();
}
onSelect(hero: Hero) { this.selectedHero = hero; }
}
mock-heroes.ts
import {Hero} from './hero';
export var HEROES: Hero[] = [
{ "id": 11, "name": "奥巴马" },
{ "id": 12, "name": "希维尔" },
{ "id": 13, "name": "兰博" },
{ "id": 14, "name": "雷克顿" },
{ "id": 15, "name": "提莫" },
{ "id": 16, "name": "德芙兰" },
{ "id": 17, "name": "德玛" },
{ "id": 18, "name": "波比" },
{ "id": 19, "name": "布兰德" },
{ "id": 20, "name": "卡尔" }
];