当前位置: 首页 > news >正文

【CuteJavaScript】Angular6入门项目(3.编写服务和引入RxJS)

本文目录

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

本项目源码放在github

四、编写服务

截止到这部分,我们的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-mailpingan8787@qq.com
博 客www.pingan8787.com
微 信pingan8787
每日文章推荐github.com/pingan8787/…
JS小册js.pingan8787.com
微信公众号前端自习课

相关文章:

  • ahjesus 让我的MVC web API支持JsonP跨域
  • 《剑指offer》分解让复杂问题更简单
  • 文件编码
  • 关于springcloud Gateway中的限流
  • 老婆!辛苦了
  • 精品思维导图,流程图模板分享
  • ubuntu制作本地源
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • Activiti数据库
  • pdf文件如何在线转换为jpg图片
  • ###STL(标准模板库)
  • mysql-5.6的GTID复制的实现
  • 整理一些计算机基础知识!
  • QMake study(part 3)
  • 制作公安系统产品思路
  • Android Volley源码解析
  • Angular数据绑定机制
  • CEF与代理
  • fetch 从初识到应用
  • gcc介绍及安装
  • isset在php5.6-和php7.0+的一些差异
  • PermissionScope Swift4 兼容问题
  • PHP CLI应用的调试原理
  • php的插入排序,通过双层for循环
  • Protobuf3语言指南
  • Spark学习笔记之相关记录
  • Spring Security中异常上抛机制及对于转型处理的一些感悟
  • 安装python包到指定虚拟环境
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 猴子数据域名防封接口降低小说被封的风险
  • 容器服务kubernetes弹性伸缩高级用法
  • 学习笔记TF060:图像语音结合,看图说话
  • 用简单代码看卷积组块发展
  • 责任链模式的两种实现
  • 字符串匹配基础上
  • MPAndroidChart 教程:Y轴 YAxis
  • mysql 慢查询分析工具:pt-query-digest 在mac 上的安装使用 ...
  • #在线报价接单​再坚持一下 明天是真的周六.出现货 实单来谈
  • (1)(1.13) SiK无线电高级配置(六)
  • (ctrl.obj) : error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MDd_DynamicDebug”不匹配值“
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (PyTorch)TCN和RNN/LSTM/GRU结合实现时间序列预测
  • (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通
  • (六)vue-router+UI组件库
  • (源码版)2024美国大学生数学建模E题财产保险的可持续模型详解思路+具体代码季节性时序预测SARIMA天气预测建模
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)Linux整合apache和tomcat构建Web服务器
  • (转)Scala的“=”符号简介
  • (转载)从 Java 代码到 Java 堆
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • ./configure、make、make install 命令
  • .L0CK3D来袭:如何保护您的数据免受致命攻击
  • .Net 路由处理厉害了
  • .NET下ASPX编程的几个小问题
  • @ResponseBody