资讯专栏INFORMATION COLUMN

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

RebeccaZhong / 2181人阅读

摘要:发布通过回调方法向发布事件。观察者一个回调函数的集合,它知道如何去监听由提供的值。

本文目录

一、项目起步

二、编写路由组件

三、编写页面组件

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结构:


《{{books.title}}》介绍

书本标题: {{books.title}}

书本作者: {{books.author}}

书本id: {{books.id}}

暂无信息

知识点
这里使用了*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 (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout requestAnimationFrame 或其他。

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 {
  return of(BookList);
}

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

改造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...
JS小册 js.pingan8787.com
微信公众号 前端自习课

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/102025.html

相关文章

  • CuteJavaScriptAngular6入门项目(1.构建项目创建路由)

    摘要:启动服务,并打开新窗口可简写创建新组件可简写创建新服务创建路由模块其他另外还有很多的命令提供,详细可以查阅官方文档命令。引入路由模块导出路由模块的指令这里需要添加一个数组,并传入,导出让路由器的相关指令可以在中的组件中使用。 本文目录 一、项目起步 二、编写路由组件 三、编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四、编写服务 1.为什么需要服务 2....

    bergwhite 评论0 收藏0
  • CuteJavaScriptAngular6入门项目(2.构建项目页面组件)

    摘要:编写单一组件我们首先写一个书本信息的组件,代码如下单个课本像火焰像灰烬程姬知识点是一个的复写器指令,就像中的和中的。写到这里,看看我们项目,还是一样正常在运行,只是现在项目中组件分工更加明确了。 本文目录 一、项目起步 二、编写路由组件 三、编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四、编写服务 1.为什么需要服务 2.编写服务 五、...

    Lemon_95 评论0 收藏0
  • CuteJavaScriptAngular6入门项目(4.改造组件添加HTTP服务

    摘要:然后我们在父组件上添加事件监听,并传入本地的在对应的中添加方法再来,我们在子组件上多导入和,并添加修饰器和调用这样就实现了我们父子组件之间的事件传递啦,现在我们的页面还是正常运行,并且删除一条数据后,页面数据会更新。 本文目录 一、项目起步 二、编写路由组件 三、编写页面组件 1.编写单一组件 2.模拟数据 3.编写主从组件 四、编写服务 1.为什么需要服务 ...

    BDEEFE 评论0 收藏0
  • CuteJavaScript】GraphQL真香入门教程

    摘要:最终代码省略其他输入类型用标识查询类型需要至少定义一个不要会不显示查询这里需要转成数组因为前面定义了返回值是类型相当于数据库的添加操作相当于数据库的更新操作省略其他现在我们可以启动服务器,在上测试下效果了。 showImg(https://segmentfault.com/img/remote/1460000019142304?w=893&h=438); 看完复联四,我整理了这份 Gr...

    bingo 评论0 收藏0
  • 初探Angular6.x---主从组件

    摘要:在上一篇博文用户列表与详情展示中我们用实现了用户列表的展示并通过语法实现了列表单击时将单击的对象传到后台的功能最后为了防止初次加载对象为空导致的错误我们又使用了语法来对要展示的详情对象进行判空操作但随着后续模块的增多以及业务的交叉我们    在上一篇博文《Angular6.x---用户列表与详情展示》中,我们用ngFor=let object of list实现了用户列表的展示,并通过...

    FingerLiu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<