本文目录一、项目起步二、编写路由组件三、编写页面组件1.编写单一组件2.模拟数据3.编写主从组件四、编写服务1.为什么需要服务2.编写服务五、引入RxJS1.关于RxJS2.引入RxJS3.改造数据获取方式六、改造组件1.添加历史记录组件2.添加和删除历史记录七、HTTP改造1.引入HTTP2.通过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.tsimport { Injectable } from ‘@angular/core’;@Injectable({ providedIn: ‘root’})新导入了@Injectable装饰器,是为了让BooksService提供一个可注入的服务,并且它还可以拥有自己的待注入的依赖,简单理解就是如果你的服务需要依赖,那么你就需要导入它。 并且它接收该服务的元数据对象。2.编写服务接下来我们开始编写books.service.ts服务。导入服务所需组件这里我们导入Books和BookList,并添加一个getBooks方法来返回所有书本的数据,并且还需要添加一个getBooks方法来返回指定id的书本信息:// index.component.tsimport { 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.tsimport { BooksService } from ‘../books.service’;export class IndexComponent implements OnInit { books : Books[]; ngOnInit() {}}然后注入我们的BooksService服务,需要先往构造函数中添加一个私有的booksservice,使用注入的BooksService作为类型,理解成一个注入点:// index.component.tsconstructor(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.tsimport { 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。什么是RxJSRxJS全称Reactive Extensions for JavaScript,中文意思: JavaScript的响应式扩展。 RxJS主要是提供一种更加强大和优雅的方式,来利用响应式编程的模式,实现JavaScript的异步编程。RxJS优点纯净性;流动性;RxJS核心概念RxJS 是基于观察者模式和迭代器模式以函数式编程思维来实现的。RxJS 中含有两个基本概念:Observables 与 Observer。 Observables 作为被观察者,是一个值或事件的流集合;而 Observer 则作为观察者,根据 Observables 进行处理。它们之间的订阅发布关系(观察者模式) 如下: 订阅:Observer 通过 Observable 提供的 subscribe() 方法订阅 Observable。 发布:Observable 通过回调 next 方法向 Observer 发布事件。 ———— 来源Angular修仙之路 RxJS Observable 另外这里列出来一些核心,具体还是看官网咯,并且下面使用到的时候会具体介绍。Observable (可观察对象): 表示一个概念,这个概念是一个可调用的未来值或事件的集合。Observer(观察者): 一个回调函数的集合,它知道如何去监听由 Observable 提供的值。Subscription (订阅): 表示 Observable 的执行,主要用于取消 Observable 的执行。Operators (操作符): 采用函数式编程风格的纯函数 (pure function),使用像 map、filter、concat、flatMap 等这样的操作符来处理集合。Subject (主体): 相当于 EventEmitter,并且是将值或事件多路推送给多个 Observer 的唯一方式。Schedulers (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 setTimeout 或 requestAnimationFrame 或其他。2.引入RxJS在我们的真实应用中,我们必须要等到服务器响应后,我们才能获取到数据,因此这天生就需要用异步思维来操作。 由于Angular中已经自带RxJS,所以我们只要在需要使用的时候,引入即可使用:3.改造数据获取方式了解完RxJS的一些概念后,我们开始改造下这些书本的数据获取方式。改造BooksService首先我们从 RxJS 中导入 Observable 和 of 符号:// books.service.tsimport { Observable, of } from ‘rxjs’;知识点: Observable: 观察者模式中的观察者,具体可以参考 Angular修仙之路 RxJS Observable of: 用来获取观察者拿到的数据,通常是一个Observable。 然后修改getBookList方法// books.service.tsgetBookList(): Observable<Books[]> { return of(BookList);}这里 of(BookList) 返回一个 Observable<Books[]>,它会发出单个值,这个值就是这些模拟书本的数组。改造IndexComponent这里也要修改getBooks方法,使用subscribe去订阅服务返回回来的值:// index.component.tsgetBooks(): void{ this.booksservice.getBookList() .subscribe(books => this.books = books);}由于原本直接赋值数据,在实际场景中是不可能这样同步的,所以这里subscribe函数,会在Observable发出数据以后,再把书本列表传到里面的回调函数,再复制给books属性。 使用这种异步方式,当 BooksService 从远端服务器获取英雄数据时,不用担心还没拿到数据就执行后面。 下一步,我们就要改造一下项目了。 本部分内容到这结束Author王平安E-mailpingan8787@qq.com博 客www.pingan8787.com微 信pingan8787每日文章推荐https://github.com/pingan8787…JS小册js.pingan8787.com微信公众号前端自习课