前言
我们为什么要用服务,因为我们的组件不能直接获取或者保存数据,我们也并不知情是展示的假数据,我们应该将数据访问委托给某个服务,此次我们不在用new创建服务,利用依赖注入机制。
Angular服务是单例对象,在应用程序的生命周期只实例化一次,也可以说是一个中间站或者是缓冲区,我们做一个栗子,我们看病的时候:医生开处方–》护士接过处方–》护士根据处方给你注射药物; 这个时候护士接过处方就是我们injector注入器,我们很多的医生都已将处方交给护士咯。
制作过程
此次制作还是在英雄列表基础上来制作的,我们目的将此方法在源代码基础上加以组件化。
- 首先我们使用angular CLI创建一个名为hero的服务。
ng generate service hero
- 其次我们在此类中导入Hero/HEROES,并且添加getHeroes方法,目的让他返回模拟的英雄列表 :参考上图照片。
import { Hero } from './hero';
import { HEROES } from './mock-heroes';
getHeroes(): Hero[] {
return HEROES;
}
- 接着我们需要在heroes.conponent.ts中导入HeroService,并且删除掉HEROES的导入即可,接着我们会在此类中进行相应的修改,请看:
// import { HEROES } from '../mock-heroes';
import { HeroService } from '../hero.service';
//并且在此类中将heroes属性改为 ,在新建的hero.service已经写上了对应的方法:以下所有代码都写在此类中export中:
heroes : Hero[];
//在此类中添加此代码,这是私有的herService,目的是声明这个属性,将它标记为HeroService的注入点: (写在heroes属性下面)
constructor(private heroService: HeroService){ }
//接着我们需要添加一个getHeroes()函数,从服务中调取英雄用:
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
//我们为了让构造函数简单,我们只做初始化操作,所以我们利用生命周期钩子,:
ngOnInit() {
this.getHeroes();
}
重构
添加Observable,我们利用这种异步方式目的是让他发出单个值,我们利用这个调用去获取我们的英雄数组.
- 我们在HeroService文件从Rxjs中导入OBservable和of符号。
import { Observable, of } from 'rxjs';
- 将HeroService文件中的getHeroes()方法改为:
getHeroes(): Observable<Hero[]> {
return of(HEROES);
}
//of(HEROES)会返回一个Observable<Hero[]>,发出单个值的英雄数组。
- 我们修改heroes.component.ts中的getHeroes方法:
//我们在此类中订阅函数,我们就可以直接获取数据了
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
新版本
上面我们用到了Observer,现在我们用一个全安全级别的MessageService,我们将此注入到HeroService中,用于获取英雄数据时显示消息。
- CLI创建MessageComponent,并将此添加到app.component.html中用于显示整个MessageComment中的内容
ng generate component messages
<h1>{{title}}</h1>
<app-heroes></app-heroes>
<app-messages></app-messages>
- 我们创建一个MessageService类用于写MessageComment的代码,然后添加到里面即可。
ng generate service message
// MessageService全部代码:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MessageService {
messages: string[] = [];
//往缓存中添加一条消息
add(message: string) {
this.messages.push(message);
}
// 用于清空缓存
clear() {
this.messages = [];
}
}
- 我们将新添加的这个类注入到HeroService中:
// 在hero.service.ts中添加此代码
import { MessageService } from './message.service';
// 我们需要修改此代码:
constructor(private messageService: MessageService) { }
// 接着我们需要接受此消息,修改getHeroes方法
getHeroes(): Observable<Hero[]> {
// TODO :send the message _arter_ fetching the heroes
this.messageService.add('HeroService: fetched heroes');
return of (HEROES);
- 我们打开messages.component.ts,我们导入此类(MessageService),然后修改我们的构造函数,添加一个公有的MessageService属性。
import { MessageService } from '../message.service';
在export中修改此函数:
constructor(public messageService: MessageService) {}
- 我们将MessageComponent模板修改,就是绑定到messageService组件中:
<div *ngIf="messageService.messages.length">
<h2>Messages</h2>
<button class="clear"
(click)="messageService.clear()">clear</button>
<div *ngFor='let message of messageService.messages'> {{message}} </div>
</div>
// *ngIf只有在有消息的时候才会显示消息区,
// click事件放在这里是为了每次单击都会显示数据。
调试
如果我们的代码只报警告,没有报错误但是没有东西显示,那么我们就把最近新添加的组件进行调试:
一条简单的调试的方法,先确定是哪个组件加载不出来,比方说我们如何确定messages加载不出来,我们就去app.component.html中将这个组件加载的地方注释掉(Ctrl+/),然后如果加载出来了则说明是这个里面的问题,如果这个里面代码没有问题的话就重新新建立一个,然后逐层将代码写进去就排查出来了!