【CuteJavaScript】Angular6入門項(xiàng)目(3.編寫服務(wù)和引入RxJS)

本文目錄

  • 一、項(xiàng)目起步
  • 二千埃、編寫路由組件
  • 三、編寫頁面組件
  • 四忆植、編寫服務(wù)
    • 1.為什么需要服務(wù)
    • 2.編寫服務(wù)
  • 五放可、引入RxJS
    • 1.關(guān)于RxJS
    • 2.引入RxJS
    • 3.改造數(shù)據(jù)獲取方式
  • 六、改造組件
    • 1.添加歷史記錄組件
    • 2.添加和刪除歷史記錄
  • 七朝刊、HTTP改造
    • 1.引入HTTP
    • 2.通過HTTP請(qǐng)求數(shù)據(jù)
    • 3.通過HTTP修改數(shù)據(jù)
    • 4.通過HTTP增加數(shù)據(jù)
    • 5.通過HTTP刪除數(shù)據(jù)
    • 6.通過HTTP查找數(shù)據(jù)

本項(xiàng)目源碼放在github

四耀里、編寫服務(wù)

截止到這部分,我們的BooksComponent組件獲取和顯示的都是本地模擬的數(shù)據(jù)拾氓。
接下來我們要開始對(duì)這些進(jìn)行重構(gòu)冯挎,讓聚焦于為它的視圖提供支持,這也讓它更容易使用模擬服務(wù)進(jìn)行單元測(cè)試咙鞍。

1.為什么需要服務(wù)

我們不應(yīng)該讓組件來直接獲取或保存數(shù)據(jù)房官,它們應(yīng)該聚焦于展示數(shù)據(jù),而數(shù)據(jù)訪問的工作交給其他服務(wù)來做奶陈。
這里我們需要?jiǎng)?chuàng)建一個(gè)名為BooksService的服務(wù)易阳,讓我們應(yīng)用中所有的類都使用它來獲取書本列表的數(shù)據(jù),使用的時(shí)候吃粒,只需要將它通過Angular的依賴注入機(jī)制注入到需要用的組件的構(gòu)造函數(shù)中潦俺。

知識(shí)點(diǎn):
服務(wù)可以實(shí)現(xiàn)多個(gè)不同組件之間信息共享,后面我們還會(huì)將它注入到兩個(gè)地方:
BooksService中徐勃,使用該服務(wù)發(fā)送消息事示。
IndexService中,使用該服務(wù)來展示消息僻肖。

接下來我們使用命令行肖爵,創(chuàng)建BooksService

ng g service books

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

// books.service.ts
import { Injectable } from '@angular/core';
@Injectable({
  providedIn: 'root'
})

新導(dǎo)入了@Injectable裝飾器,是為了讓BooksService提供一個(gè)可注入的服務(wù)臀脏,并且它還可以擁有自己的待注入的依賴劝堪,簡單理解就是如果你的服務(wù)需要依賴冀自,那么你就需要導(dǎo)入它
并且它接收該服務(wù)的元數(shù)據(jù)對(duì)象秒啦。

2.編寫服務(wù)

接下來我們開始編寫books.service.ts服務(wù)熬粗。

  • 導(dǎo)入服務(wù)所需組件

這里我們導(dǎo)入BooksBookList,并添加一個(gè)getBooks方法來返回所有書本的數(shù)據(jù)余境,并且還需要添加一個(gè)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)
  }
}

在我們使用這個(gè)服務(wù)之前驻呐,需要先注冊(cè)該服務(wù),因?yàn)槲覀冊(cè)谑褂?code>ng g service books命令創(chuàng)建服務(wù)時(shí)芳来,CLI已經(jīng)默認(rèn)為我們添加了注冊(cè)了含末,這是方法就是上面代碼中的:

providedIn: 'root'

表示將我們的服務(wù)注冊(cè)在根注入器上,這樣我們就可以把這個(gè)服務(wù)注入到任何享用的類上了即舌。

  • 修改IndexComponent

先刪除BookList的引入佣盒,并修改books屬性的定義:

// index.component.ts
import { BooksService } from '../books.service';
export class IndexComponent implements OnInit {
  books : Books[];
  ngOnInit() {}
}

然后注入我們的BooksService服務(wù),需要先往構(gòu)造函數(shù)中添加一個(gè)私有的booksservice顽聂,使用注入的BooksService作為類型沼撕,理解成一個(gè)注入點(diǎn):

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

之后我們需要添加一個(gè)getBooks方法來獲取這些書本數(shù)據(jù),并在生命周期函數(shù)ngOnInit中調(diào)用:

export class IndexComponent implements OnInit {
  ngOnInit() {
    this.getBooks();
  }
  getBooks(): void{
    this.books = this.booksservice.getBookList();
  }
}
  • 修改DetailComponent
    我們先改造書本詳情頁的HTML結(jié)構(gòu):
<!-- detail.component.html -->
<div *ngIf="books" class="detail">
  <h3>《{{books.title}}》介紹</h3>
  <div>
    <img src="{{books.url}}">
  </div>
  <p>書本標(biāo)題: {{books.title}}</p>
  <p>書本作者: {{books.author}}</p>
  <p>書本id: {{books.id}}</p>
</div>
<div *ngIf="!books" class="detail">
  <h3>暫無信息</h3>
</div>

知識(shí)點(diǎn)
這里使用了*ngIf指令芜飘,當(dāng)條件為true則顯示其HTML內(nèi)容。

// 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服務(wù)
  ) { }

  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方法嗦明,當(dāng)剛進(jìn)入頁面時(shí),將書本id傳入getBooks方法蚪燕,去BooksService去獲取對(duì)應(yīng)id的書本信息娶牌,并復(fù)制給變量books,然后展示到頁面馆纳。

改造之后诗良,我們的頁面顯示依舊正常。

圖片3-2

但是我們要知道鲁驶,這背后的邏輯已經(jīng)改變了鉴裹。

五、引入RxJS改造項(xiàng)目

1.關(guān)于RxJS

這里簡單介紹關(guān)鍵概念钥弯,具體可以查看 RxJS 官網(wǎng)径荔,也可以參考 淺析Angular之RxJS

什么是RxJS

RxJS全稱Reactive Extensions for JavaScript脆霎,中文意思: JavaScript的響應(yīng)式擴(kuò)展总处。
RxJS主要是提供一種更加強(qiáng)大和優(yōu)雅的方式,來利用響應(yīng)式編程的模式睛蛛,實(shí)現(xiàn)JavaScript的異步編程鹦马。

RxJS優(yōu)點(diǎn)

  • 純凈性胧谈;
  • 流動(dòng)性;

RxJS核心概念

RxJS 是基于觀察者模式和迭代器模式以函數(shù)式編程思維來實(shí)現(xiàn)的荸频。RxJS 中含有兩個(gè)基本概念:ObservablesObserver菱肖。
Observables 作為被觀察者,是一個(gè)值或事件的流集合试溯;而 Observer 則作為觀察者蔑滓,根據(jù) Observables 進(jìn)行處理。它們之間的訂閱發(fā)布關(guān)系(觀察者模式) 如下:
訂閱Observer 通過 Observable 提供的 subscribe() 方法訂閱 Observable遇绞。
發(fā)布Observable 通過回調(diào) next 方法向 Observer 發(fā)布事件键袱。

———— 來源Angular修仙之路 RxJS Observable

另外這里列出來一些核心,具體還是看官網(wǎng)咯摹闽,并且下面使用到的時(shí)候會(huì)具體介紹蹄咖。

  • Observable (可觀察對(duì)象): 表示一個(gè)概念,這個(gè)概念是一個(gè)可調(diào)用的未來值或事件的集合付鹿。
  • Observer(觀察者): 一個(gè)回調(diào)函數(shù)的集合澜汤,它知道如何去監(jiān)聽由 Observable 提供的值。
  • Subscription (訂閱): 表示 Observable 的執(zhí)行舵匾,主要用于取消 Observable 的執(zhí)行俊抵。
  • Operators (操作符): 采用函數(shù)式編程風(fēng)格的純函數(shù) (pure function),使用像 map坐梯、filter徽诲、concatflatMap 等這樣的操作符來處理集合吵血。
  • Subject (主體): 相當(dāng)于 EventEmitter谎替,并且是將值或事件多路推送給多個(gè) Observer 的唯一方式。
  • Schedulers (調(diào)度器): 用來控制并發(fā)并且是中央集權(quán)的調(diào)度員蹋辅,允許我們?cè)诎l(fā)生計(jì)算時(shí)進(jìn)行協(xié)調(diào)钱贯,例如 setTimeoutrequestAnimationFrame或其他。

2.引入RxJS

在我們的真實(shí)應(yīng)用中侦另,我們必須要等到服務(wù)器響應(yīng)后秩命,我們才能獲取到數(shù)據(jù),因此這天生就需要用異步思維來操作淋肾。

由于Angular中已經(jīng)自帶RxJS硫麻,所以我們只要在需要使用的時(shí)候,引入即可使用:

3.改造數(shù)據(jù)獲取方式

了解完RxJS的一些概念后樊卓,我們開始改造下這些書本的數(shù)據(jù)獲取方式拿愧。

  • 改造BooksService

首先我們從 RxJS 中導(dǎo)入 Observableof 符號(hào):

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

知識(shí)點(diǎn)
Observable: 觀察者模式中的觀察者,具體可以參考 Angular修仙之路 RxJS Observable
of: 用來獲取觀察者拿到的數(shù)據(jù)碌尔,通常是一個(gè)Observable浇辜。

然后修改getBookList方法

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

這里 of(BookList) 返回一個(gè)Observable<Books[]>券敌,它會(huì)發(fā)出單個(gè)值,這個(gè)值就是這些模擬書本的數(shù)組柳洋。

  • 改造IndexComponent

這里也要修改getBooks方法待诅,使用subscribe去訂閱服務(wù)返回回來的值:

// index.component.ts
getBooks(): void{
  this.booksservice.getBookList()
    .subscribe(books => this.books = books);
}

由于原本直接賦值數(shù)據(jù),在實(shí)際場(chǎng)景中是不可能這樣同步的熊镣,所以這里subscribe函數(shù)卑雁,會(huì)在Observable發(fā)出數(shù)據(jù)以后,再把書本列表傳到里面的回調(diào)函數(shù)绪囱,再復(fù)制給books屬性测蹲。
使用這種異步方式,當(dāng) BooksService 從遠(yuǎn)端服務(wù)器獲取英雄數(shù)據(jù)時(shí)鬼吵,不用擔(dān)心還沒拿到數(shù)據(jù)就執(zhí)行后面扣甲。

下一步,我們就要改造一下項(xiàng)目了齿椅。

本部分內(nèi)容到這結(jié)束

Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推薦 https://github.com/pingan8787/Leo_Reading/issues
JS小冊(cè) js.pingan8787.com
微信公眾號(hào) 前端自習(xí)課
前端自習(xí)課
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琉挖,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子涣脚,更是在濱河造成了極大的恐慌示辈,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,376評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件遣蚀,死亡現(xiàn)場(chǎng)離奇詭異顽耳,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)妙同,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來膝迎,“玉大人粥帚,你說我怎么就攤上這事∶⑽校” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵卖漫,是天一觀的道長费尽。 經(jīng)常有香客問我,道長羊始,這世上最難降的妖魔是什么旱幼? 我笑而不...
    開封第一講書人閱讀 56,432評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮突委,結(jié)果婚禮上柏卤,老公的妹妹穿的比我還像新娘冬三。我一直安慰自己,他們只是感情好缘缚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評(píng)論 6 385
  • 文/花漫 我一把揭開白布勾笆。 她就那樣靜靜地躺著,像睡著了一般桥滨。 火紅的嫁衣襯著肌膚如雪窝爪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評(píng)論 1 290
  • 那天齐媒,我揣著相機(jī)與錄音蒲每,去河邊找鬼。 笑死里初,一個(gè)胖子當(dāng)著我的面吹牛啃勉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播双妨,決...
    沈念sama閱讀 38,933評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼淮阐,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了刁品?” 一聲冷哼從身側(cè)響起泣特,我...
    開封第一講書人閱讀 37,701評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎挑随,沒想到半個(gè)月后状您,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡兜挨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評(píng)論 2 327
  • 正文 我和宋清朗相戀三年膏孟,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拌汇。...
    茶點(diǎn)故事閱讀 38,626評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柒桑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出噪舀,到底是詐尸還是另有隱情魁淳,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評(píng)論 4 329
  • 正文 年R本政府宣布与倡,位于F島的核電站界逛,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏纺座。R本人自食惡果不足惜息拜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧该溯,春花似錦岛抄、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氯庆,卻和暖如春蹭秋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背堤撵。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工仁讨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人实昨。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓洞豁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親荒给。 傳聞我的和親對(duì)象是個(gè)殘疾皇子丈挟,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容