首页 > 其他分享 >【Angular】162-Angular6入门项目(三)

【Angular】162-Angular6入门项目(三)

时间:2022-11-28 14:00:55浏览次数:47  
标签:Observable 服务 id Angular6 books RxJS Angular 162 BooksService


本文目录

一、项目起步

二、编写路由组件

三、编写页面组件

  • 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查找数据

八、结语


这个入门项目是我学习完Angular 英雄指南教程(https://angular.cn/tutorial)后,自己手写的一个练习项目,一步一步来,最终的项目源码可以原文链接查看,大佬们请指点啦。


四、编写服务

截止到这部分,我们的 ​​BooksComponent​​​组件获取和显示的都是本地模拟的数据。
接下来我们要开始对这些进行重构,让聚焦于为它的视图提供支持,这也让它更容易使用模拟服务进行单元测试。

1.为什么需要服务

我们不应该让组件来直接获取或保存数据,它们应该聚焦于展示数据,而数据访问的工作交给其他服务来做。
这里我们需要创建一个名为 ​​​BooksService​​的服务,让我们应用中所有的类都使用它来获取书本列表的数据,使用的时候,只需要将它通过Angular的依赖注入机制注入到需要用的组件的构造函数中。

知识点:
服务可以实现多个不同组件之间信息共享,后面我们还会将它注入到两个地方:
​​​BooksService​​​中,使用该服务发送消息。
​​​IndexService​​中,使用该服务来展示消息。

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

  1. ​ng g service books​

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

  1. ​// books.service.ts​
  2. ​import { Injectable } from '@angular/core';​
  3. ​@Injectable({​
  4. ​ providedIn: 'root'​
  5. ​})​

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

2.编写服务

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

  • 导入服务所需组件

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

  1. ​// index.component.ts​
  2. ​import { Books } from './books';​
  3. ​import { BookList } from './mock-books';​
  4. ​@Injectable({​
  5. ​ providedIn: 'root'​
  6. ​})​
  7. ​export class BooksService {​
  8. ​ constructor() { }​
  9. ​ getBookList(): Books[] {​
  10. ​ return BookList;​
  11. ​ }​
  12. ​ getBook(id: number): Books{​
  13. ​ return BookList.find(book => book.id === id)​
  14. ​ }​
  15. ​}​

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

  1. ​providedIn: 'root'​

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

  • 修改 ​​IndexComponent​

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

  1. ​// index.component.ts​
  2. ​import { BooksService } from '../books.service';​
  3. ​export class IndexComponent implements OnInit {​
  4. ​ books : Books[];​
  5. ​ ngOnInit() {}​
  6. ​}​

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

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

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

  1. ​export class IndexComponent implements OnInit {​
  2. ​ ngOnInit() {​
  3. ​ this.getBooks();​
  4. ​ }​
  5. ​ getBooks(): void{​
  6. ​ this.books = this.booksservice.getBookList();​
  7. ​ }​
  8. ​}​
  • 修改 ​​DetailComponent​​我们先改造书本详情页的HTML结构:
  1. ​<!-- detail.component.html -->​
  2. ​<div *ngIf="books" class="detail">​
  3. ​ <h3>《{{books.title}}》介绍</h3>​
  4. ​ <div>​
  5. ​ <img src="{{books.url}}">​
  6. ​ </div>​
  7. ​ <p>书本标题: {{books.title}}</p>​
  8. ​ <p>书本作者: {{books.author}}</p>​
  9. ​ <p>书本id: {{books.id}}</p>​
  10. ​</div>​
  11. ​<div *ngIf="!books" class="detail">​
  12. ​ <h3>暂无信息</h3>​
  13. ​</div>​

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

  1. ​// detail.component.ts​
  2. ​import { Books } from '../books';​
  3. ​import { BooksService } from '../books.service';​
  4. ​export class DetailComponent implements OnInit {​
  5. ​ constructor(​
  6. ​ private route: ActivatedRoute,​
  7. ​ private location: Location,​
  8. ​ private booksservice: BooksService // 引入BooksService服务​
  9. ​ ) { }​

  10. ​ books: Books; // 定义books类型​
  11. ​ ngOnInit() {​
  12. ​ this.getDetail()​
  13. ​ }​
  14. ​ getDetail(): void{​
  15. ​ const id = +this.route.snapshot.paramMap.get('id');​
  16. ​ this.getBooks(id);​
  17. ​ }​
  18. ​ getBooks(id: number): void {​
  19. ​ this.books = this.booksservice.getBook(id);​
  20. ​ }​
  21. ​}​

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

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


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

五、引入RxJS改造项目

1.关于RxJS

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

什么是RxJS

RxJS全称 ​​ReactiveExtensionsforJavaScript​​​,中文意思: 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​​​ (操作符): 采用函数式编程风格的纯函数 ( ​​purefunction​​),使用像 ​​map​​、 ​​filter​​、 ​​concat​​、 ​​flatMap​​ 等这样的操作符来处理集合。
  • ​Subject​​​ (主体): 相当于 ​​EventEmitter​​,并且是将值或事件多路推送给多个 ​​Observer​​ 的唯一方式。
  • ​Schedulers​​​ (调度器): 用来控制并发并且是中央集权的调度员,允许我们在发生计算时进行协调,例如 ​​setTimeout​​ 或 ​​requestAnimationFrame​​或其他。

2.引入RxJS

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

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

3.改造数据获取方式

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

  • 改造 ​​BooksService​

首先我们从 RxJS 中导入 ​​Observable​​​ 和 ​​of​​ 符号:

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

知识点
​​​Observable​​​: 观察者模式中的观察者,具体可以参考 Angular修仙之路 RxJS Observable
​​​of​​​: 用来获取观察者拿到的数据,通常是一个 ​​Observable​​。

然后修改 ​​getBookList​​方法

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

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

  • 改造 ​​IndexComponent​

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

  1. ​// index.component.ts​
  2. ​getBooks(): void{​
  3. ​ this.booksservice.getBookList()​
  4. ​ .subscribe(books => this.books = books);​
  5. ​}​

由于原本直接赋值数据,在实际场景中是不可能这样同步的,所以这里 ​​subscribe​​​函数,会在 ​​Observable​​​发出数据以后,再把书本列表传到里面的回调函数,再复制给 ​​books​​​属性。
使用这种异步方式,当 ​​​BooksService​​ 从远端服务器获取英雄数据时,不用担心还没拿到数据就执行后面。

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

【Angular】162-Angular6入门项目(三)_ide


标签:Observable,服务,id,Angular6,books,RxJS,Angular,162,BooksService
From: https://blog.51cto.com/u_11887782/5891103

相关文章

  • Angular样式隔离(style isolation)及选择器(:host, :host-context, ::ng-deep)的使用
    1.Angular样式隔离Angular样式隔离的好处最最要的一条就是CSS的可维护性。当没有样式隔离时,我们创建一个组件并添加样式后,可能会影响到其他的组件样式,而且很有可能查找不......
  • 力扣162(java&python)-寻找峰值(中等)
    题目:峰值元素是指其值严格大于左右相邻值的元素。给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可......
  • angularjs解决播放语音出错的问题
    首先是看了github上的这个​​https://github.com/angular/angular.js/issues/1352​​,知道了语音播放不了了,下面是正确的播放代码首先添加过滤器app.filter("trustUrl",['......
  • angularjs解析html字符串
    参考链接​​https://docs.angularjs.org/api/ngSanitize​​首先下载angular-sanitize.min.js,下载地址:​​https://github.com/angular/bower-angular-sanitize​​添加解......
  • MBR16200CT-ASEMI插件肖特基二极管MBR16200CT
    编辑-ZMBR16200CT在TO-220AB封装里采用的2个芯片,其尺寸都是102MIL,是一款插件肖特基二极管。MBR16200CT的浪涌电流Ifsm为200A,漏电流(Ir)为0.05mA,其工作时耐温度范围为-65~175......
  • MBR16200CT-ASEMI插件肖特基二极管MBR16200CT
    编辑-ZMBR16200CT在TO-220AB封装里采用的2个芯片,其尺寸都是102MIL,是一款插件肖特基二极管。MBR16200CT的浪涌电流Ifsm为200A,漏电流(Ir)为0.05mA,其工作时耐温度范围为-65~1......
  • MBR16200FCT-ASEMI塑封肖特基二极管MBR16200FCT
    编辑:llMBR16200FCT-ASEMI塑封肖特基二极管MBR16200FCT型号:MBR16200FCT品牌:ASEMI封装:ITO-220AB正向电流:16A反向电压:200V引线数量:3芯片个数:2芯片尺寸:102MIL漏电流:10ua恢复时间......
  • MBR16200FCT-ASEMI塑封肖特基二极管MBR16200FCT
    编辑:llMBR16200FCT-ASEMI塑封肖特基二极管MBR16200FCT型号:MBR16200FCT品牌:ASEMI封装:ITO-220AB正向电流:16A反向电压:200V引线数量:3芯片个数:2芯片尺寸:102MIL漏电流:1......
  • MBR16200CT-ASEMI半塑封肖特基二极管MBR16200CT
    编辑:llMBR16200CT-ASEMI半塑封肖特基二极管MBR16200CT型号:MBR16200CT品牌:ASEMI封装:TO-220AB特性:肖特基二极管正向电流:16A反向耐压:200V恢复时间:5ns引脚数量:3芯片......
  • angular 预备知识
    安装1先安装node.js2安装淘宝cnpm第一种:直接安装cnpm安装淘宝提供的cnpm,并更改服务器地址为淘宝的国内地址,命令:npminstall-gcnpm--registry=https://registry......