本文目录

  • 一、项目起步
  • 二、编写路由组件
  • 三、编写页面组件
  • 四、编写服务
    • 1.为什么需要服务
    • 2.编写服务
  • 五、引入RxJS
    • 1.关于RxJS
    • 2.引入RxJS
    • 3.改造数据获取方式
  • 六、改造组件
    • 1.添加历史记录组件
    • 2.添加和删除历史记录
  • 七、HTTP改造
    • 1.引入HTTP
    • 2.通过HTTP请求数据
    • 3.通过HTTP修改数据
    • 4.通过HTTP增加数据
    • 5.通过HTTP删除数据
    • 6.通过HTTP查找数据

四、编写服务

截止到这部分,我们的BooksComponent组件获取和显示的都是本地模拟的数据。

接下来我们要开始对这些进行重构,让聚焦于为它的视图提供支持,这也让它更容易使用模拟服务进行单元测试。

1.为什么需要服务

我们不应该让组件来直接获取或保存数据,它们应该聚焦于展示数据,而数据访问的工作交给其他服务来做。

这里我们需要创建一个名为BooksService的服务,让我们应用中所有的类都使用它来获取书本列表的数据,使用的时候,只需要将它通过Angular的依赖注入机制注入到需要用的组件的构造函数中。

知识点:

服务可以实现多个不同组件之间信息共享,后面我们还会将它注入到两个地方:

BooksService中,使用该服务发送消息。

IndexService中,使用该服务来展示消息。

接下来我们使用命令行,创建BooksService

ng g service books

在生成的books.service.ts文件中:

// books.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})

新导入了@Injectable装饰器,是为了让BooksService提供一个可注入的服务,并且它还可以拥有自己的待注入的依赖,简单理解就是如果你的服务需要依赖,那么你就需要导入它

并且它接收该服务的元数据对象。

2.编写服务

接下来我们开始编写books.service.ts服务。

  • 导入服务所需组件

这里我们导入BooksBookList,并添加一个getBooks方法来返回所有书本的数据,并且还需要添加一个getBooks方法来返回指定id的书本信息:

// index.component.ts
import { Books } from './books';
import { BookList } from './mock-books';
@Injectable({
providedIn: 'root'
})
export class BooksService {
constructor() { }
getBookList(): Books[] {
return BookList;
}
getBook(id: number): Books{
return BookList.find(book => book.id === id)
}
}

在我们使用这个服务之前,需要先注册该服务,因为我们在使用ng g service books命令创建服务时,CLI已经默认为我们添加了注册了,这是方法就是上面代码中的:

providedIn: 'root'

表示将我们的服务注册在根注入器上,这样我们就可以把这个服务注入到任何享用的类上了。

  • 修改IndexComponent

先删除BookList的引入,并修改books属性的定义:

// index.component.ts
import { BooksService } from '../books.service';
export class IndexComponent implements OnInit {
books : Books[];
ngOnInit() {}
}

然后注入我们的BooksService服务,需要先往构造函数中添加一个私有的booksservice,使用注入的BooksService作为类型,理解成一个注入点:

// index.component.ts
constructor(private booksservice: BooksService) { }

之后我们需要添加一个getBooks方法来获取这些书本数据,并在生命周期函数ngOnInit中调用:

export class IndexComponent implements OnInit {
ngOnInit() {
this.getBooks();
}
getBooks(): void{
this.books = this.booksservice.getBookList();
}
}
  • 修改DetailComponent

    我们先改造书本详情页的HTML结构:
<!-- detail.component.html -->
<div *ngIf="books" class="detail">
<h3>《{{books.title}}》介绍</h3>
<div>
<img src="{{books.url}}">
</div>
<p>书本标题: {{books.title}}</p>
<p>书本作者: {{books.author}}</p>
<p>书本id: {{books.id}}</p>
</div>
<div *ngIf="!books" class="detail">
<h3>暂无信息</h3>
</div>

知识点

这里使用了*ngIf指令,当条件为true则显示其HTML内容。

// detail.component.ts
import { Books } from '../books';
import { BooksService } from '../books.service';
export class DetailComponent implements OnInit {
constructor(
private route: ActivatedRoute,
private location: Location,
private booksservice: BooksService // 引入BooksService服务
) { } books: Books; // 定义books类型
ngOnInit() {
this.getDetail()
}
getDetail(): void{
const id = +this.route.snapshot.paramMap.get('id');
this.getBooks(id);
}
getBooks(id: number): void {
this.books = this.booksservice.getBook(id);
}
}

这段代码,主要定义了getBooks方法,当刚进入页面时,将书本id传入getBooks方法,去BooksService去获取对应id的书本信息,并复制给变量books,然后展示到页面。

改造之后,我们的页面显示依旧正常。

但是我们要知道,这背后的逻辑已经改变了。

五、引入RxJS改造项目

1.关于RxJS

这里简单介绍关键概念,具体可以查看 RxJS 官网,也可以参考 浅析Angular之RxJS

什么是RxJS

RxJS全称Reactive Extensions for JavaScript,中文意思: JavaScript的响应式扩展。

RxJS主要是提供一种更加强大和优雅的方式,来利用响应式编程的模式,实现JavaScript的异步编程。

RxJS优点

  • 纯净性;
  • 流动性;

RxJS核心概念

RxJS 是基于观察者模式和迭代器模式以函数式编程思维来实现的。RxJS 中含有两个基本概念:ObservablesObserver

Observables 作为被观察者,是一个值或事件的流集合;而 Observer 则作为观察者,根据 Observables 进行处理。它们之间的订阅发布关系(观察者模式) 如下:

订阅Observer 通过 Observable 提供的 subscribe() 方法订阅 Observable

发布Observable 通过回调 next 方法向 Observer 发布事件。

———— 来源Angular修仙之路 RxJS Observable

另外这里列出来一些核心,具体还是看官网咯,并且下面使用到的时候会具体介绍。

  • Observable (可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。
  • Observer(观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。
  • Subscription (订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。
  • Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 mapfilterconcatflatMap 等这样的操作符来处理集合。
  • Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。
  • Schedulers (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeoutrequestAnimationFrame或其他。

2.引入RxJS

在我们的真实应用中,我们必须要等到服务器响应后,我们才能获取到数据,因此这天生就需要用异步思维来操作。

由于Angular中已经自带RxJS,所以我们只要在需要使用的时候,引入即可使用:

3.改造数据获取方式

了解完RxJS的一些概念后,我们开始改造下这些书本的数据获取方式。

  • 改造BooksService

首先我们从 RxJS 中导入 Observableof 符号:

// books.service.ts
import { Observable, of } from 'rxjs';

知识点

Observable: 观察者模式中的观察者,具体可以参考 Angular修仙之路 RxJS Observable

of: 用来获取观察者拿到的数据,通常是一个Observable

然后修改getBookList方法

// books.service.ts
getBookList(): Observable<Books[]> {
return of(BookList);
}

这里 of(BookList) 返回一个Observable<Books[]>,它会发出单个值,这个值就是这些模拟书本的数组。

  • 改造IndexComponent

这里也要修改getBooks方法,使用subscribe去订阅服务返回回来的值:

// index.component.ts
getBooks(): void{
this.booksservice.getBookList()
.subscribe(books => this.books = books);
}

由于原本直接赋值数据,在实际场景中是不可能这样同步的,所以这里subscribe函数,会在Observable发出数据以后,再把书本列表传到里面的回调函数,再复制给books属性。

使用这种异步方式,当 BooksService 从远端服务器获取英雄数据时,不用担心还没拿到数据就执行后面。

下一步,我们就要改造一下项目了。

本部分内容到这结束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787/Leo_Reading/issues
JS小册 js.pingan8787.com
微信公众号 前端自习课

【CuteJavaScript】Angular6入门项目(3.编写服务和引入RxJS)的更多相关文章

  1. 【CuteJavaScript】Angular6入门项目(4.改造组件和添加HTTP服务)

    本文目录 一.项目起步 二.编写路由组件 三.编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四.编写服务 1.为什么需要服务 2.编写服务 五.引入RxJS 1.关于RxJS 2.引 ...

  2. 【CuteJavaScript】Angular6入门项目(1.构建项目和创建路由)

    本文目录 一.项目起步 二.编写路由组件 三.编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四.编写服务 1.为什么需要服务 2.编写服务 五.引入RxJS 1.关于RxJS 2.引 ...

  3. 【CuteJavaScript】Angular6入门项目(2.构建项目页面和组件)

    本文目录 一.项目起步 二.编写路由组件 三.编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四.编写服务 1.为什么需要服务 2.编写服务 五.引入RxJS 1.关于RxJS 2.引 ...

  4. WCF入门-项目间调用服务

    练习WCF入库,添加了一个WCF项目,同时添加了一个控制台程序,在控制台程序启动时,调用WCF服务,报错. 控制台程序代码为: namespace WcfConsumer { class Progra ...

  5. JAVA WEB快速入门之从编写一个基于SpringBoot+Mybatis快速创建的REST API项目了解SpringBoot、SpringMVC REST API、Mybatis等相关知识

    JAVA WEB快速入门系列之前的相关文章如下:(文章全部本人[梦在旅途原创],文中内容可能部份图片.代码参照网上资源) 第一篇:JAVA WEB快速入门之环境搭建 第二篇:JAVA WEB快速入门之 ...

  6. JAVA WEB快速入门之从编写一个JSP WEB网站了解JSP WEB网站的基本结构、调试、部署

    接上篇<JAVA WEB快速入门之环境搭建>,在完成了环境搭建后(JDK.Tomcat.IDE),现在是万事具备,就差写代码了,今天就来从编写一个JSP WEB网站了解JSP WEB网站的 ...

  7. [转贴]systemd 编写服务管理脚本

    [转贴]sparkdev大神的博客, 关于 systemd的配置文件的 介绍, 自己之前二进制安装 k8s 时 超过一个 service文件 但是当时不明不白的. 现在再学习一下大神的文章 的确牛B ...

  8. SpringCloud学习之手把手教你用IDEA搭建入门项目(三)

    本篇博客是承接上一篇<手把手教你用IDEA搭建SpringCloud入门项目(二)>,不清楚的请到我的博客空间查看后再看本篇博客,上面两篇博客成功创建了一个简单的SpringCloud项目 ...

  9. TensorFlowSharp入门使用C#编写TensorFlow人工智能应用

    TensorFlowSharp入门使用C#编写TensorFlow人工智能应用学习. TensorFlow简单介绍 TensorFlow 是谷歌的第二代机器学习系统,按照谷歌所说,在某些基准测试中,T ...

随机推荐

  1. pat 1027 Colors in Mars(20 分)

    1027 Colors in Mars(20 分) People in Mars represent the colors in their computers in a similar way as ...

  2. Kali Rolling 系统配置总结 (Updateing)

    主系统Kali Linux确实好用,继<Kali~2018安装后的配置>之后,自己又全面详细的总结了关于Kali Linux系统安装后的配置,<Kali Rolling 系统配置总结 ...

  3. 领扣(LeetCode)Fizz Buzz 个人题解

    写一个程序,输出从 1 到 n 数字的字符串表示. 1. 如果 n 是3的倍数,输出“Fizz”: 2. 如果 n 是5的倍数,输出“Buzz”: 3.如果 n 同时是3和5的倍数,输出 “FizzB ...

  4. 【故障公告】docker swarm 集群问题造成新版博客后台故障

    非常抱歉,今天下午 16:55~17:05 左右,由于 docker swarm 集群的突发不稳定问题造成新版博客后台(目前处于灰度发布阶段)无法正常使用,由此给您带来麻烦,请您谅解. 出故障期时,新 ...

  5. Vue_声明周期

    Vue生命周期 在vue2.0的时候,声明钩子发生了改变,具体有八个 <!-- HTML部分 --> <div id="app"> <div>{ ...

  6. ceph中rbd的增量备份和恢复

    ceph中rbd的增量备份和恢复 ceph的文档地址:Ceph Documentation ​ 在调研OpenStack中虚机的备份和恢复时,发现OpenStack和ceph紧密结合,使用ceph做O ...

  7. sed和awk的简单使用

    sed是一个很好的文件处理工具,本身是一个管道命令,主要是以  行 为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法. 语法: sed [-nefri] ‘ ...

  8. 前端API层架构,也许你做得还不够

    上午好,今天为大家分享下个人对于前端API层架构的一点经验和看法.架构设计是一条永远走不完的路,没有最好,只有更好.这个道理适用于软件设计的各个场景,前端API层的设计也不例外,如果您觉得在调用接口时 ...

  9. HttpClient POST/SET方法

    前言: 网络API接口:https://api.apiopen.top/searchMusic 此API接口返回类型为JSON格式类型 GET:从指定资源请求数据 POST:向指定资源提交要被处理的数 ...

  10. shell特殊符号及cut、sort_wc_uniq、tee_tr_split命令 使用介绍

    第6周第2次课(4月24日) 课程内容: 8.10 shell特殊符号cut命令8.11 sort_wc_uniq命令8.12 tee_tr_split命令8.13 shell特殊符号下 扩展1. s ...