Javascript 在不刷新页面的情况下使用可观察对象的CRUD
我试图在angular中使用observables实现CRUD,而不在Javascript 在不刷新页面的情况下使用可观察对象的CRUD,javascript,angular,typescript,rxjs,Javascript,Angular,Typescript,Rxjs,我试图在angular中使用observables实现CRUD,而不在ts文件中订阅它们,而是在html中使用async 我的目标是获取、添加、编辑和删除从服务器获取的项目,而无需在每次请求后刷新页面 我试着用行为主题,重放主题,异步主题来做这件事,还寻找了一些资料,但我没有发现任何有用的东西 有人能举个例子说明如何用最好的模式实现这种crud吗 在下面,我粘贴了我以前尝试过的代码和API返回的数据结构 提前谢谢 在documents.service.ts中 import { HttpClien
ts
文件中订阅它们,而是在html
中使用async
我的目标是获取、添加、编辑和删除从服务器获取的项目,而无需在每次请求后刷新页面
我试着用行为主题
,重放主题
,异步主题
来做这件事,还寻找了一些资料,但我没有发现任何有用的东西
有人能举个例子说明如何用最好的模式实现这种crud吗
在下面,我粘贴了我以前尝试过的代码和API返回的数据结构
提前谢谢
在documents.service.ts中
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class DocumentsService {
constructor(private http: HttpClient) { }
getDocuments(): Observable<any[]> {
return this.http.get<any[]>(`https://localhost:5001/docs`)
}
postDocument(item: any): Observable<any> {
return this.http.post<any[]>(`https://localhost:5001/docs`, item)
}
putDocument(id: number, item: any): Observable<any> {
return this.http.put<any[]>(`https://localhost:5001/docs/${id}`, item)
}
deleteDocument(id: number): Observable<any> {
return this.http.delete<any>(`https://localhost:5001/docs/${id}`)
}
}
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable } from 'rxjs';
import { DocumentsService } from 'src/app/services/documents.service';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent {
documents$: Observable<any> = new Observable()
constructor(private documentsService: DocumentsService) { }
ngOnInit() {
this.getDocuments();
}
getDocuments(): void {
this.documents$ = this.documentsService.getDocuments()
}
postDocument(): void {
this.documentsService.postDocument({
"title": "title",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"userName": "mike mock",
"email": "mike@mock.com"
}
})
}
putDocument(): void {
this.documentsService.putDocument(4, {
"title": "title",
"description": "lorem ipsum",
"imageUrl": "https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
"madeBy": {
"userName": "mike mock",
"email": "mike@mock.com"
}
})
}
deleteDocument(): void {
this.documentsService.deleteDocument(5)
}
}
在documents.component.html中
家庭作业
加我
编辑我
删除我
{{document | json}}
HTTP获取响应:
[
{
“id”:47,
“标题”:“码头工人”,
“描述”:“lorem ipsum”,
“imageUrl”:https://images.pexels.com/photos/3464632/pexels-photo-3464632.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
“马德比”:{
“用户名”:“迈克·莫克”,
“电子邮件”:mike@mock.com"
}
},
{
“id”:49,
“标题”:“linux”,
“描述”:“第二描述”,
“imageUrl”:https://images.pexels.com/photos/3900437/pexels-photo-3900437.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
“马德比”:{
“用户名”:“迈克·莫克”,
“电子邮件”:mike@mock.com"
}
}
]
HTTP POST/PUT/DELETE响应:
{
“id”:50,
“标题”:“一些文字”,
“描述”:“lorem ipsum”,
“imageUrl”:https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
“马德比”:{
“用户名”:“迈克·莫克”,
“电子邮件”:mike@mock.com"
}
}
可观察对象是惰性的,在订阅之前不会执行
将组件更新为:
从'@angular/core'导入{Component,OnInit};
从'@angular/Router'导入{Router};
从“rxjs”导入{observeable,BehaviorSubject};
从'src/app/services/documents.service'导入{DocumentsService};
@组成部分({
选择器:“应用程序主页”,
templateUrl:“./home.component.html”,
样式URL:['./home.component.scss']
})
导出类HomeComponent{
documents$:BehaviorSubject=新的BehaviorSubject(未定义);
构造函数(私有文档服务:文档服务){}
恩戈尼尼特(){
此文件为.getDocuments();
}
getDocuments():void{
this.documentsService.getDocuments().subscribe(this.documents$);
}
postDocument():void{
this.documents服务.postDocument({
“头衔”:“头衔”,
“描述”:“lorem ipsum”,
“imageUrl”:https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
“马德比”:{
“用户名”:“迈克·莫克”,
“电子邮件”:mike@mock.com"
}
}).subscribe(=>this.getDocuments());
}
putDocument():void{
本文件服务文件(4{
“头衔”:“头衔”,
“描述”:“lorem ipsum”,
“imageUrl”:https://images.pexels.com/photos/2765111/pexels-photo-2765111.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
“马德比”:{
“用户名”:“迈克·莫克”,
“电子邮件”:mike@mock.com"
}
}).subscribe(=>this.getDocuments());
}
deleteDocument():void{
this.documentsService.deleteDocument(5).subscribe(=>this.getDocuments());
}
}
我还强烈建议您键入api并删除any
的使用问题出在您的服务中。在您的服务中,getDocuments()只是对后端进行调用。在组件中编写此.documents$=this.documentsService.getDocuments()时,它将调用函数一次,读取数据,以后再也不会更新它
因此,您需要创建一个主题来存储服务中的数据,使用.asObservable()使其在外部可用,将组件链接到该可观察对象,并在每次http调用后更新主题的内容
大概是这样的:
export class DocumentsService {
private _documents$ = new BehaviorSubject<Array<Document>>([]);
public documents$: Observable<Array<Document>>;
constructor(private http: HttpClient) {
this.documents$ = this._documents$.asObservable()
}
getDocuments(): Observable<any[]> {
this.http.get<any[]>(`https://localhost:5001/docs`).switchmap(
(response) => this._documents$.next(response)
)
}
postDocument(item: any): Observable<any> {
# update _documents$ here
}
putDocument(id: number, item: any): Observable<any> {
# update _documents$ here
}
deleteDocument(id: number): Observable<any> {
# update _documents$ here
}
}
它应该会起作用。这对你来说可能有点过头了,但我建议包括一家商店。每个CRUD操作都是一个单击即可分派的操作。请求由effects发送,您的组件仅从store中选择文档。@MoxxiManagarm,我认为向正在构建简单CRUD应用程序的新手建议状态管理选项是不合适的。谢谢您的建议,我通常使用强类型,但是对于这个问题,我将类型更改为any
,以避免使这个问题复杂化。异步管道为您进行订阅。这就是使用异步管道的全部要点。请更新你的答案,这完全是错误的,因为我没有回答你问题中关于获取更新数据的部分。您可以从其他方法中调用此.getDocuments()。我将更新我的答案以显示。@Jean XavierRaynaud,请查看作者的原始postDocument、putDocument和deleteDocument方法。作者问题中的异步管道仅执行其CRUD应用程序的读取部分。@mikolajs,如果您想在出现错误时刷新数据,也可以在此用例中使用管道finalize。作者的postDocument,putDocument和deleteDocument方法在未订阅的情况下不会调用服务方法。请用更新后的组件部分更新您的答案。@j如果它们基本上都是琐碎的事情,只需从服务器读取响应,并在switchman或排气图中更新行为主题。postDocument(项目:any):Observable
将不会在作者的当前消费组件中执行,因为它返回一个Observable,并且需要订阅<代码>postDocument():中的void
this.documents$ = this.documentsService.documents$