本文目录

  • 一、项目起步
  • 二、编写路由组件
  • 三、编写页面组件
  • 四、编写服务
    • 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. hdu 1024 Max Sum Plus Plus (动态规划)

    Max Sum Plus PlusTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  2. Netty创建服务器与客户端

    Netty 创建Server服务端 Netty创建全部都是实现自AbstractBootstrap.客户端的是Bootstrap,服务端的则是ServerBootstrap. 创建一个 HelloSe ...

  3. 安装win7和ubuntu16.04双系统

    硬件:2012年本子  话硕A55V Service 准备: 首先通过一键还原备份win7系统!不清楚某些失误会不会备份也不能拯救! 清出100g硬盘空间,ubuntu会安装在这里 查看当前win7启 ...

  4. GDG Xi'an DevFest 2019 闪电演讲 -《假如我是一个浏览器》PPT(经典多图,建议收藏)

    GDG Xi'an DevFest2019演讲PPT链接: http://tmp.link/f/5dd9e6bf461b6 闪电演讲<假如我是一个浏览器>PPT链接: https://gi ...

  5. 初探three.js光源

    上一节我们简单的说了一下THREE中必要的元素.今天我们深入探讨一下各种THREE的光源. 一 基础光源 基础光源有4种1.THREE.AmbientLight(环境光源)2.THREE.PointL ...

  6. html——标签基础

    img标签:使用  src="xxx" 来链接图片 当图片显示不出来的时候  显示alt 中定义的内容 当图片显示了出来  鼠标移动到图片上的时候 显示的是  title 中定义的 ...

  7. Lua和C交互的简易教程

    转载请标明出处:http://blog.csdn.net/shensky711/article/details/52458051 本文出自: [HansChen的博客] Lua栈 要理解Lua和C++ ...

  8. 国内开源C# WPF控件库Panuon.UI.Silver强力推荐

    国内优秀的WPF开源控件库,Panuon.UI的优化版本.一个漂亮的.使用样式与附加属性的WPF UI控件库,值得向大家推荐使用与学习. 今天站长(Dotnet9,站长网址:https://dotne ...

  9. 微信浏览器跳转浏览器下载app解决方案

    新版本微信浏览器中,已禁用下载APP应用,只支持打开微信合作商APP下载,所以无法通过微信浏览器直接下载APP应用.列举微信浏览器下载APP的种解决方案: 方案:通过Url 跳转到手机默认浏览器,或者 ...

  10. 特殊权限set_uid、set_gid、stick_bit、软链接、硬链接文件 使用介绍

    第2周第4次课(3月29日) 课程内容:2.18 特殊权限set_uid2.19 特殊权限set_gid2.20 特殊权限stick_bit2.21 软链接文件2.22 硬链接文件     2.18  ...