如何从 ParamMap 中获取路由参数并将其分配给 属性

How do I get the route parameter out of ParamMap and assign it to a property

我 运行 Angular 6 岁,RxJs 6 岁。

我正在尝试从 paramMap 中获取值并将其分配给 属性。路线如下所示:

{
    path: 'post/:postName',
    component: PostComponent
}

post 组件当前如下所示:

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { ActivatedRoute, ParamMap } from '@angular/router';
import { switchMap } from 'rxjs/operators';
import { Observable, of } from 'rxjs';
import * as matter from 'yaml-front-matter';
import { Post } from '../../models/post';

@Component({
  selector: 'blog-post',
  templateUrl: './post.component.html',
  styleUrls: ['./post.component.css'],
  encapsulation: ViewEncapsulation.Emulated
})
export class PostComponent implements OnInit {
  created: Date;
  postName = '';
  markdown = '';
  title = '';
  loading = true;
  author = '';

  constructor(private route: ActivatedRoute) { }

  async ngOnInit () {
    this.route.paramMap.pipe(
      switchMap((params: ParamMap) =>
        of(params.get('postName'))
      )
    ).subscribe(d => this.postName = d);

    const file = await fetch(`/_posts/${this.postName}.md`);
    const text = await file.text();
    const content = text.trim();
    this.parseFrontMatter(content);
  }

  parseFrontMatter (content: string) {
    const frontMatter: Post = matter.loadFront(content);
    this.title = frontMatter.title;
    this.author = frontMatter.author;
    this.created = frontMatter.created;
    this.markdown = frontMatter.__content;
    this.loading = false;
  }
}

在 ngOnInit 中是从 paramMap 中获取值的代码。除非您尝试使用不同的参数路由回 post 组件,否则此代码有效。

这可以在 Devbin.io 上观察到。

  1. 导航至 post 页面
  2. 点击唯一post
  3. 现在尝试导航到另一个 post.
  4. 的关于页面
  5. 请注意,即使 Url 已更新,它也不会路由到“关于”页面。

可以在 GitHub

上找到完整的源代码

所有文档和其他 Stack Overflow 答案始终假设您要在 switchMap 函数中调用服务。官方文档是here

我的问题是如何获取路线参数并将其分配给 属性 并在导航回同一路线时保持导航正常工作?

所以我克隆了 repo 并解决了这个问题。

替换为:

   async ngOnInit () {
        this.route.paramMap.pipe(
          switchMap((params: ParamMap) =>
            of(params.get('postName'))
          )
        ).subscribe(d => this.postName = d);

        const file = await fetch(`/_posts/${this.postName}.md`);
        const text = await file.text();
        const content = text.trim();
        this.parseFrontMatter(content);
      }

具有以下内容:

  ngOnInit() {
    this.route.paramMap.pipe(
      switchMap((params: ParamMap) =>
        of(params.get('postName'))
      )
    ).subscribe(d => {
      this.postName = d;

      fetch(`/_posts/${this.postName}.md`)
        .then(data => data.text()
          .then(text => {
            const content = text.trim();
            this.parseFrontMatter(content);
          }));
    });
  }

说明: 您仅在组件初始化时才获取帖子,因为您的文件获取代码在 Observable 订阅方法之外。我搬进来并链接了承诺,然后将最终值传递给你的函数 parseFrontMatter

这是因为当您路由到同一组件时,不会调用 ngOnInit。在您的情况下 /post/Angular-6-Router-How-To-Get-Route-Parameters 和 /post/About 触发相同的组件:post.component.

因此,为了完成这项工作,您可以在 paramMap.pipe 中调用订阅内的函数。

你可以这样做:

ngOnInit() {
    this.route.paramMap.pipe(
      switchMap((params: ParamMap) =>
        of(params.get('postName'))
      )
    ).subscribe((d) => {
      this.postName = d;
      this.postInit();
    });

  }

  async postInit() {
    const file = await fetch(`/_posts/${this.postName}.md`);
    const text = await file.text();
    const content = text.trim();
    this.parseFrontMatter(content);
  }

  parseFrontMatter(content: string) {
    const frontMatter: Post = matter.loadFront(content);
    this.title = frontMatter.title;
    this.author = frontMatter.author;
    this.created = frontMatter.created;
    this.markdown = frontMatter.__content;
    this.loading = false;
  }