可观察的对象(observable)的数据
在现在的是情况下:HeroService.getHeroes() 的函数签名是同步的,它所隐含的假设是 HeroService 总是能同步获取英雄列表数据。 而 HeroesComponent 也同样假设能同步取到 getHeroes() 的结果。但是在实际的项目中,这种情况几乎是不可能实现的,因为,在实际的项目中,这些数据是来源于远端的服务器上,而这个过程始终是一个异步的过程。
在实际的项目中:HeroService 必须等服务器给出响应, 而 getHeroes() 不能立即返回英雄数据, 浏览器也不会在该服务等待期间停止响应。HeroService.getHeroes() 必须具有某种形式的异步函数签名。它可以使用回调函数,可以返回 Promise(承诺),也可以返回 Observable(可观察对象)。
一. 重新写一个可观察对象版本的 HeroService
Observable简介:Observable 是 RxJS中的一个关键类。
1.打开 HeroService 文件,并从 RxJS 中导入 Observable 和 of 符号。
import { Observable, of } from 'rxjs';
2. 修改getHeroes 方法。
getHeroes(): Observable<Hero[]> {
return of(HEROES);
}
注意:of(HEROES) 会返回一个 Observable<Hero[]>,它会发出单个值,这个值就是这些模拟英雄的数组。
### 3.在 HeroesComponent 中订阅 之前的HeroService.getHeroes 方法返回的是一个 Hero[],现在它返回的是 Observable<Hero[]>。所以现在必须在 HeroesComponent 中也向本服务中的这种Observable形式变化。
修改getHeroes():
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
Observable.subscribe() 是关键的差异点。
两个版本的差别:
第一个版本:
hero的数组赋值给了该组件的 heroes 属性。 这种赋值是同步的,这里包含的假设是服务器能立即返回hero数组或者浏览器能在等待服务器响应时冻结界面,使其等到后端的数据返回以后,界面在再次解冻。
第二个版本:
应用会等待Observable 发出这个hero数组,这种请求可能立即发生,也可能会在几分钟之后。 然后,subscribe 函数把这个hero数组传给这个回调函数,该函数把hero数组赋值给组件的 heroes 属性。使用这种异步方式,当 HeroService 从远端服务器获取hero数据时,应用就可以工作了。(此过程可以想像类似的想像于将界面暂时冻结,然后等到远端的服务器将需要的数据返回以后,自动的将界面又重新的解冻,使应用重新开始工作)
二. 显示信息
学习目标:
-
添加一个 MessagesComponent,它在屏幕的底部显示应用中的消息。
-
创建一个可注入的、全应用级别的 MessageService,用于发送要显示的消息。
-
把 MessageService 注入到 HeroService 中。
-
当 HeroService 成功获取了英雄数据时显示一条消息。
1.创建MessagesComponent(推荐使用CLI创建)
E:\angular-workspace\new-angularaa>ng generate component messages
CREATE src/app/messages/messages.component.css (0 bytes)
CREATE src/app/messages/messages.component.html (27 bytes)
CREATE src/app/messages/messages.component.spec.ts (642 bytes)
CREATE src/app/messages/messages.component.ts (277 bytes)
UPDATE src/app/app.module.ts (638 bytes)
CLI 在 src/app/messages中创建了组件文件,并且把 MessagesComponent 声明在了 AppModule 中。
2.修改 AppComponent 的模板来显示所生成的 MessagesComponent
<h1>{{title}}</h1>
<app-heroes></app-heroes>
<app-messages></app-messages>
<app-messages>
是MessagesComponent的 selector: ‘app-messages’
3.创建 MessageService
E:\angular-workspace\new-angularaa>ng generate service messages
CREATE src/app/messages.service.spec.ts (386 bytes)
CREATE src/app/messages.service.ts (137 bytes)
4.在MessagesService中增加一个message的变量,并且在写一个新增message的方法和清空message的方法。
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageService {
// messages 变量
messages: string[] = [];
// 增加变量的函数
add(message: string) {
this.messages.push(message);
}
// 清空变量的函数
clear() {
this.messages = [];
}
// 构造方法
constructor() {
}
}
5.把它注入到 HeroService 中
打开 HeroService,将导入 MessageService。
import { MessageService } from './message.service';
6.修改这个构造函数
添加一个私有的 messageService 属性参数。 Angular 将会在创建 HeroService 时把 MessageService 的单例注入到这个属性中。
constructor(private messageService: MessageService) { }
7.从 HeroService 中发送一条消息
修改 getHeroes 方法,在获取到英雄数组时发送一条消息。
getHeroes(): Observable<Hero[]> {
this.messageService.add('HeroService: fetched heroes');
return of(HEROES);
}
8.从 HeroService 中显示消息
打开 MessagesComponent,并且导入 MessageService。
import { MessagesService } from '../messages.service';
修改MessagesComponent构造函数,添加一个 public 的 messageService 属性。Angular 将会在创建 MessagesComponent 的实例时把 MessageService 的实例注入到这个属性中。
此处设messageService为public是因为要在messageService在模版文件中用到。
constructor(public messagesService: MessagesService) { }
9.绑定到 MessageService
修改messageComponent的模版文件
<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 只有在有消息时才会显示消息区。
-
*ngFor用来在一系列 <div> 元素中展示消息列表。
-
Angular 的事件绑定把按钮的 click 事件绑定到了 MessageService.clear()这个方法上了。
10.Message加css样式
为MessagesComponent组件添加私有样式
h2 {
color: red;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: crimson;
font-family: Cambria, Georgia;
}
button.clear {
font-family: Arial;
background-color: #eee;
border: none;
padding: 5px 10px;
border-radius: 4px;
cursor: pointer;
cursor: hand;
}
button:hover {
background-color: #cfd8dc;
}
button:disabled {
background-color: #eee;
color: #aaa;
cursor: auto;
}
button.clear {
color: #888;
margin-bottom: 12px;
}
扫码加好友
(转载本站文章请注明作者和出处 追梦er)