如何正确输出一个detail post的模板?

How to output a template of detail post rightly?

我正在写学习项目Angular。我的项目显示 https://jsonplaceholder.typicode.com/ 中的 posts。我想显示详细的 post 模板(例如 localhost:3000/posts/1)。我在方法 getById 中的 posts.service.ts 处得到一个特定的 post。现在我有一个错误 - “类型 'Subscription' 与类型 'Post' 没有共同的属性”。但我不知道如何解决这个问题。我的错误在哪里?如何解决?如何正确输出模板({{ post.title }})?

此处所有项目:posts project

post.service.ts:

import { HttpClient } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";

export interface Post {
  title: string;
  userId?: number;
}

@Injectable({ providedIn: "root" })
export class PostService {
  private _postsURL = "https://jsonplaceholder.typicode.com";

  constructor(private http: HttpClient) {}

  public fetchPosts(page: number, itemsPerPage: number): Observable<Post[]> {
    let posts = this.http.get<Post[]>(`${this._postsURL}/posts`);

    return this.getPageItems(posts, page, itemsPerPage);
  }

  private getPageItems(
    posts: Observable<Post[]>,
    page: number,
    itemsPerPage: number
  ): Observable<Post[]> {
    return posts.pipe(
      map((u) => {
        let startIndex = itemsPerPage * (page - 1);
        return u.slice(startIndex, startIndex + itemsPerPage);
      })
    );
  }

  getById(id: number) {
    let post = this.http
      .get<Post[]>(`${this._postsURL}/posts/${id}`)
      .subscribe();

    return post;
  }
}

post.component.ts:

import { Component, OnInit } from "@angular/core";
import { ActivatedRoute, Params } from "@angular/router";
import { Post, PostService } from "../post.service";

@Component({
  selector: "app-post",
  templateUrl: "./post.component.html"
})
export class PostComponent implements OnInit {
  post: any;

  constructor(
    private route: ActivatedRoute,
    private postsService: PostService
  ) {}

  ngOnInit(): void {
    this.route.params.subscribe((params: Params) => {
      this.post = this.postsService.getById(+params.id);
    });
  }
}

post.component.html:

<div>
    post component
    <h1>{{ post.title }}</h1>
</div>

您可以更改代码中的多项内容以完成这项工作并遵循最佳做法。 当组件被销毁时,异步管道还将负责取消订阅可观察对象,因此您不必手动取消订阅它。

它在变化检测方面也更有效。

在你 post.service 中将 getById 更改为 return observable:

另外,如果您想查看结构化的 HTML json 响应,您可以使用“

”标签。

getById(id: number): Observable<Post> {
    return this.http.get<Post>(`${this._postsURL}/posts/${id}`);
}

和post.component.html到:

<div>
  post component
  <h1>{{ (post | async )?.title }}</h1>
  <pre>{{ (post | async) }}</pre> // you can see structured json
</div>

请检查固定样本:

https://codesandbox.io/s/trusting-drake-zgri7?file=/src/app/post/post.component.ts

有多种方法可以解决这个问题。我会提出以下解决方案:

在服务中,您可以return observable。在这里,您将 return 类型转换为 Observable 以 returning 订阅。所以将其更改为:此外,它是 returning 单个 Post 而不是 Post[]。请验证。

getById(id: number): Observable<Post> {
   let post = this.http.get<Post>(`${this._postsURL}/posts/${id}`);
    return post;
}

在 html 中,您可以使用异步管道获取标题的值:

<h1>{{ (post | async)?.title }}</h1>