簡體   English   中英

CRUD 使用 observables 而不刷新頁面

[英]CRUD using observables without refreshing page

我正在嘗試在 angular 中使用可觀察對象而不在ts文件中訂閱它們但在html中使用async來實現 CRUD。

我的目標是獲取、添加、編輯和刪除從服務器獲取的項目,而無需在每次請求后刷新頁面。

我嘗試用BehaviorSubjectReplaySubjectAsyncSubject來做這件事,並且還尋找材料,但我沒有發現任何有用的東西。

有人可以舉一個例子如何以最好的模式實現這種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}`)
  }
}

documents.component.ts

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

<p routerLink="/">home works!</p>

<button (click)="postDocument()">add me</button>
<button (click)="putDocument()">edit me</button>
<button (click)="deleteDocument()">delete me</button>


<p *ngFor="let document of documents$ | async">
    {{ document | json }}
</p>

HTTP 獲取響應:

[
  {
    "id": 47,
    "title": "docker",
    "description": "lorem ipsum",
    "imageUrl": "https://images.pexels.com/photos/3464632/pexels-photo-3464632.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "madeBy": {
      "username": "mike mock",
      "email": "mike@mock.com"
    }
  },
  {
    "id": 49,
    "title": "linux",
    "description": "second description",
    "imageUrl": "https://images.pexels.com/photos/3900437/pexels-photo-3900437.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500",
    "madeBy": {
      "username": "mike mock",
      "email": "mike@mock.com"
    }
  }
]

HTTP POST/PUT/DELETE 響應:

{
  "id": 50,
  "title": "some text",
  "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"
  }
}

Observables 是惰性的,在訂閱之前不會執行。

將您的組件更新為:

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, BehaviorSubject } 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$: BehaviorSubject<any> = new BehaviorSubject(undefined);

  constructor(private documentsService: DocumentsService) { }
  
  ngOnInit() {
    this.getDocuments();
  }

  getDocuments(): void {
    this.documentsService.getDocuments().subscribe(this.documents$);
  }

  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"
      }
    }).subscribe(_ => this.getDocuments());
  }

  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"
      }
    }).subscribe(_ => this.getDocuments());
  }

  deleteDocument(): void {
    this.documentsService.deleteDocument(5).subscribe(_ => this.getDocuments());
  }
}

我還強烈建議您強烈輸入 api 並刪除any .

問題在於您的服務。 在您的服務中,您的 getDocuments() 只是簡單地調用您的后端。 當您在組件中編寫 this.documents$ = this.documentsService.getDocuments() 時,它將調用 function 一次,讀取數據並且以后不再更新。

因此,您需要創建一個主題以將數據存儲在您的服務中,使用 an.asObservable() 使其在外部可用,將您的組件鏈接到該 observable 並在每次 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
  }
}

然后在您的組件中簡單地更新您定義文檔的行

this.documents$ = this.documentsService.documents$

它應該工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM