【问题标题】:How can I change a specific, internal route parameter in Angular2如何更改 Angular2 中的特定内部路由参数
【发布时间】:2017-01-01 20:40:27
【问题描述】:

我正在构建一个可以显示不同类型数据的日历。以下示例解释了我认为的 URL 结构:

  • todo/2017/01/01待办事项的一天视图
  • birthdays/2017/01/01生日一天视图
  • todo/2017/01 待办事项的一个月视图
  • birthdays/2017/01 一个月的生日视图
  • todo/2017 todos 年视图
  • birthdays/2017 一年的生日视图

到目前为止,我已经能够传入 Date 对象并通过

重新路由
this.router.navigate([#HARDCODED# 'todo' #OR# 'birthday', year, ?month, ?day])

问题是我希望能够从todo/2017/01/01 => birthdays/2017/01/01 OR todo/2017/01 => birthdays/2017/01 导航。

所以我不能传入日期参数​​,因为根据我所在的视图,有些可能不存在。

那么我怎样才能只切换出一个内部参数并重新路由?

有点像

this.router.navigate(['todo', {ignoreTheRest: true}])

否则我必须为每个可能的组合编写一个复杂的 switch 语句。

【问题讨论】:

  • 我相信你可以通过optional route params实现你想要的,即使我以前从未这样做过。我自己需要尝试一下。
  • 可选路由参数不是解决您问题的正确方法。 András Szepesházi 的回答应该可以解决。

标签: angular typescript angular2-routing


【解决方案1】:

您可以通过内置的ActivatedRoute 服务来实现这一点,正如他们在documentation 中所说的那样,您的“路线信息一站式商店”。

首先,您需要在组件的构造函数中注入服务。假设你有一个 Todo 组件和一个 Birthday 组件,无论哪种情况,构造函数都应该是这样的:

constructor(private currentRoute: ActivatedRoute, private router: Router) { }

然后,在您的 ngOnInit() 函数中,您需要订阅您的 ActivatedRoute 实例的 url 属性,这是一个 Observable:

ngOnInit() {
    this.currentRoute.url
        .subscribe(routeParts => {
            this.periodArray = [];
            for (let i = 1; i < routeParts.length; i++) {
                this.periodArray.push(routeParts[i].path);
            }
        });
}

组件路由作为 Observable 提供的原因是,在组件的生命周期中,它可以接收多个不同的路由。就像你的情况一样“/todo/2017”或“todo/2017/01”等。你的组件只会被创建一次,ngOnInit()也只会被调用一次,但是通过订阅ActivatedRoute.url observable,你将始终收到有关当前路线的通知。

上面的代码块用激活路由中除了第一个 url 部分之外的所有部分填充了一个数组,它为您提供了除了初始“/todo”或“/birthday”段之外的所有传递参数。

现在您可以通过在此参数数组的开头添加所需的路径来导航到另一个组件,例如:

navigateBirthdays() {
    this.periodArray.unshift('/birthday');
    this.router.navigate(this.periodArray);
}

这是 Todo 组件的完整代码及其模板:

todo.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  templateUrl: './todo.component.html',
})
export class TodoComponent implements OnInit {

  periodArray = [];
  constructor(private currentRoute: ActivatedRoute, private router: Router) { }

  ngOnInit() {
    this.currentRoute.url
      .subscribe(routeParts => {
        this.periodArray = [];
        for (let i = 1; i < routeParts.length; i++) {
          this.periodArray.push(routeParts[i].path);
        }
      });
  }

  navigateBirthdays() {
    this.periodArray.unshift('/birthday');
    this.router.navigate(this.periodArray);
  }
}

todo.component.html

<p>
  List of Todo items for  {{periodArray.join("-")}}
</p>
<button (click)="navigateBirthdays()">Show Birthday items</button>

生日组件看起来几乎相同。以上允许您在“/todo/2017/1/3”和“/birthday/2017/1/3”之间以及“/todo/2017”和“/birthday/2017”等之间来回切换 -无需设置任何特定的路由规则。

附注:对于可选参数,通常最好不要将它们包含在 URL 路径中,而是将它们作为可选路由对象提供 - 请参阅文档的 this section。

【讨论】:

  • 同意这是直截了当的方法。需要补充的一点是,我们可能需要在 ngOnDestroy 中取消订阅,例如: ``` export class TodoComponent implements OnInit, OnDestroy { subscriptions = []; ... ngOnInit() { const sub = this.currentRoute.url .subscribe(...); this.subscription.push(sub); } ngOnDestroy() { this.subscription.forEach(sub => sub.unsubscribe()) } } ```
  • @Timathon 来自文档:“订阅组件中的 observable 时,您几乎总是安排在组件被销毁时取消订阅。有一些特殊的 observables 没有必要这样做。ActivatedRoute Observables 是例外之一。”但他们还补充说:“无论如何,请随时取消订阅。这是无害的,绝不是坏习惯。” :)
  • 我依稀记得“这是无害的,绝不是坏习惯(取消订阅)。”但就是想不起它的确切来源。现在我知道。谢谢。
  • 优秀的解决方案!我最终将您的 this.periodArray 转到了一个服务,我已经在其中存储了我的部分 url 历史记录,但总的来说,使用取消移位和拼接数组现在将遍及我的应用程序向前发展。
猜你喜欢
  • 1970-01-01
  • 2017-03-10
  • 2017-12-03
  • 2019-06-18
  • 1970-01-01
  • 1970-01-01
  • 2018-06-18
  • 2016-03-22
  • 1970-01-01
相关资源
最近更新 更多