Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推荐 | https://github.com/pingan8787/Leo_Reading/issues |
微信公众号 | 前端自习课 |
本文目录
- 一、项目起步
- 二、编写路由组件
- 三、编写页面组件
- 四、编写服务
- 五、引入RxJS
- 六、改造组件
- 1.添加历史记录组件
- 2.添加和删除历史记录
- 七、HTTP改造
- 1.引入HTTP
- 2.通过HTTP请求数据
- 3.通过HTTP修改数据
- 4.通过HTTP增加数据
- 5.通过HTTP删除数据
- 6.通过HTTP查找数据
六、改造组件
从这里开始,我们要使用RxJS来改造组件和添加新功能了,让整个项目更加完善。
1.添加历史记录组件
- 创建
HistoryComponent
组件然后在1
ng g component hostory
app.component.html
文件夹中添加组件:1
2<!-- app.component.html -->
<app-history></app-history>
2.添加增删改查功能
这里我们要开始做书本的增删改查功能,需要先创建一个HistoryService
服务,方便我们实现这几个功能:
创建
HistoryService
服务1
ng g service history
然后在生成的ts文件中,增加
add
和clear
方法,add
方法用来添加历史记录到history
数组中,clear
方法则是清空history
数组:1
2
3
4
5
6
7
8
9
10// history.service.ts
export class HistoryService {
history: string[] = [];
add(history: string){
this.history.push(history);
}
clear(){
this.history = [];
}
}使用
HistoryService
服务
在将这个服务,注入到BooksService
中,并改造getBooks
方法:
1 | // books.service.ts |
也可以用相同方法,在IndexComponent
中添加访问首页书本列表
的记录。
1 | // index.component.ts |
接下来,将我们的HistoryService
注入到HistoryComponent
中,然后才能将历史数据显示到页面上:
1 | // history.component.ts |
1 | <!-- history.component.html --> |
代码解释:*ngIf="historyservice.history.length"
,是为了防止还没有拿到历史数据,导致后面的报错。(click)="historyservice.clear()"
, 绑定我们服务中的clear
事件,实现清除缓存。*ngFor="let item of historyservice.history"
,将我们的历史数据渲染到页面上。
到了这一步,就能看到历史数据了,每次也换到首页,都会增加一条。
接下来,我们要在书本详情页也加上历史记录的统计,导入文件,注入服务,然后改造getBooks
方法,实现历史记录的统计:
1 | // detail.component.ts |
这时候就可以在历史记录中,看到这些操作的记录了,并且清除按钮也正常使用。
七、HTTP改造
原本我只想写到上一章,但是想到,我们实际开发中,哪有什么本地数据,基本上数据都是要从服务端去请求,所以这边也有必要引入这一张,模拟实际的HTTP请求。
1.引入HTTP
在这一章,我们使用Angular提供的 HttpClient
来添加一些数据持久化特性。
然后实现对书本数据进行获取,增加,修改,删除和查找功能。
HttpClient
是Angular通过 HTTP 与远程服务器通讯的机制。
这里我们为了让HttpClient
在整个应用全局使用,所以将HttpClient
导入到根模块app.module.ts
中,然后把它加入 @NgModule.imports
数组:
1 | import { HttpClientModule } from '@angular/common/http'; |
这边我们使用 内存 Web API(In-memory Web API) 模拟出的远程数据服务器通讯。
注意: 这个内存 Web API 模块与 Angular 中的 HTTP 模块无关。
通过下面命令来安装:
1 | npm install angular-in-memory-web-api --save |
然后在app.module.ts
中导入 HttpClientInMemoryWebApiModule
和 InMemoryDataService
类(后面创建):
1 | // app.module.ts |
知识点:forRoot()
配置方法接受一个 InMemoryDataService 类(初期的内存数据库)作为参数。
然后我们要创建InMemoryDataService
类:
1 | ng g service InMemoryData |
并将生成的in-memory-data.service.ts
修改为:
1 | // in-memory-data.service.ts |
这里先总结InMemoryDbService
所提供的RESTful API,后面都要用到:
例如如果url
是api/books
,那么
- 查询所有成员:以GET方法访问
api/books
- 查询某个成员:以GET方法访问
api/books/id
,比如id
是1
,那么访问api/books/1
- 更新某个成员:以PUT方法访问
api/books/id
- 删除某个成员:以DELETE方法访问
api/books/id
- 增加一个成员:以POST方法访问
api/books
2.通过HTTP请求数据
现在要为接下来的网络请求做一些准备,先在books.service.ts
中引入HTTP符号,然后注入HttpClient
并改造:
1 | // books.service.ts |
这里我们还新增一个私有方法log
和一个私有变量booksUrl
。
接下来我们要开始发起http请求数据,开始改造getBookList
方法:
1 | // books.service.ts |
这里我们使用 http.get
替换了 of
,其它没修改,但是应用仍然在正常工作,这是因为这两个函数都返回了 Observable<Hero[]>
。
实际开发中,我们还需要考虑到请求的错误处理,要捕获错误,我们就要使用 RxJS 的 catchError()
操作符来建立对 Observable 结果的处理管道(pipe)。
我们引入catchError
并改造原本getBookList
方法:
1 | // books.service.ts |
知识点:.pipe()
方法用来扩展 Observable
的结果。catchError()
操作符会拦截失败的 Observable。并把错误对象传给错误处理器,错误处理器会处理这个错误。handleError()
错误处理函数做了两件事,发出错误通知和返回空结果避免程序出错。
这里还需要使用tap
操作符改造getBookList
方法,来窥探Observable
数据流,它会查看Observable
的值,然后我们使用log
方法,记录一条历史记录。tap
回调不会改变这些值本身。
1 | // books.service.ts |
3.通过HTTP修改数据
这里我们需要在原来DetailComponent
上面,添加一个输入框、保存按钮和返回按钮,就像这样:
1 | <!-- detail.component.html --> |
这边切记一点,一定要在app.module.ts
中引入 FormsModule
模块,并在@NgModule
的imports
中引入,不然要报错了。
1 | // app.module.ts |
input
框绑定书本的标题books.title
,而保存按钮绑定一个save()
方法,这里还要实现这个方法:
1 | // detail.component.ts |
这里通过调用BooksService
的updateBooks
方法,将当前修改后的书本信息修改到源数据中,这里我们需要去books.service.ts
中添加updateBooks
方法:
1 | // books.service.ts |
知识点:HttpClient.put()
方法接受三个参数:URL 地址
、要修改的数据
和其他选项
。httpOptions
常量需要定义在@Injectable
修饰器之前。
现在,我们点击首页,选择一本书进入详情,修改标题然后保存,会发现,首页上这本书的名称也会跟着改变呢。这算是好了。
4.通过HTTP增加数据
我们可以新增一个页面,并添加上路由和按钮:
1 | ng g component add |
添加路由:
1 | // app-routing.module.ts |
添加路由入口:
1 | <!-- app.component.html --> |
编辑添加书本的页面:
1 | <!-- add.component.html --> |
初始化添加书本的数据:
1 | // add.component.ts |
然后在books.service.ts
中添加addBooks
方法,来添加一本书本的数据:
1 | // books.service.ts |
现在就可以正常添加书本啦。
5.通过HTTP删除数据
这里我们先为每个书本后面添加一个删除按钮,并绑定删除事件delete
:
1 | <!-- books.component.html --> |
1 | // books.component.ts |
然后还要再books.service.ts
中添加deleteBooks
方法来删除:
1 | // books.service.ts |
这里需要在删除书本结束后,通知IndexComponent
将数据列表中的这条数据删除,这里还需要再了解一下Angular 父子组件数据通信。
然后我们在父组件IndexComponent
上添加change
事件监听,并传入本地的funChange
:
1 | <!-- index.component.html --> |
在对应的index.component.ts
中添加funChange
方法:
1 | // index.component.ts |
再来,我们在子组件BooksComponent
上多导入Output
和EventEmitter
,并添加@Output()
修饰器和调用emit
:
1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core'; |
这样就实现了我们父子组件之间的事件传递啦,现在我们的页面还是正常运行,并且删除一条数据后,页面数据会更新。
6.通过HTTP查找数据
还是在books.service.ts
,我们添加一个方法getBooks
,来实现通过ID来查找指定书本,因为我们是通过ID查找,所以返回的是单个数据,这里就是Observable<Books>
类型:
1 | // books.service.ts |
注意,这里 getBooks
会返回 Observable<Books>
,是一个可观察的单个对象,而不是一个可观察的对象数组。
八、结语
这个项目其实很简单,但是我还是一步一步的写下来,一方面让自己更熟悉Angular,另一方面也是希望能帮助到更多朋友哈~
最终效果:
本部分内容到这结束
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推荐 | https://github.com/pingan8787/Leo_Reading/issues |
JS小册 | js.pingan8787.com |
微信公众号 | 前端自习课 |