3

我一直在尝试学习 angular 2 以及本教程[Build an application with Angular 2 and Firebase][1]并尝试对其进行扩展。但是我在尝试嵌套多条路线时遇到了障碍。

应用结构:

Goals – (has router-outlet)
 > Single Goal with Experiments list – (has router-outlet)
  > Single Experiment – (has router-outlet)
   > Experiment Notes

路由器设置:

export const routerConfig : Route[] = [
  {
    path: 'goals',
    children: [
      {
        path: ':id', component: SingleGoalComponent,
        children: [
          {
            path: 'experiments',
            children: [
              { path: ':id', component: ExperimentDetailsComponent,
                children: [
                  { path: '', redirectTo: 'notes', pathMatch: 'full' },
                  { path: 'notes', component: ExperimentNotesComponent }
                ]
              },
              { path: 'new', component: NewExperimentComponent },
              { path: '' }
            ]
          },
          { path: '', redirectTo: 'experiments', pathMatch: 'full' }
        ]
      },
      { path: '', component: GoalsComponent }
    ]
  },
  { path: 'notes', component: NotesComponent },
  { path: '', redirectTo: 'goals', pathMatch: 'full' },
  { path: '**', redirectTo: 'goals', pathMatch: 'full' }
];

问题

如果我单击实验列表中的实验 1,我得到goals/1/experiments/1/notes的 url 是正确的,并且我看到了正确的实验 1 的注释

如果我然后单击实验列表中的实验 2goals/1/experiments/2/notes ,则 url 是正确的,实验详细信息是正确的,但注释仍然是实验 1 的注释

如果我然后刷新浏览器,将加载实验 2,并且注释现在是实验 2 的注释,这是正确的。

这就是我获取experimentId笔记的方式

实验笔记.component.ts

experimentId: string;
  goalId: string;

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private experimentsService: ExperimentsService,
    private _location: Location) { }

  ngOnInit() {

    Observable.combineLatest(this.route.parent.params, this.route.parent.parent.params)
      .forEach((params: Params[]) => {
        this.experimentId = params[0]['id'];
        this.goalId = params[1]['id'];
      });

    console.log('Experiment ID: ' + this.experimentId + '| Goal Id: ' + this.goalId);

    this.notes$ = this.experimentsService.findAllNotesForExperiment(this.experimentId);

我确信这是我正在犯的一个明显的错误,但对于我的生活,我看不出我在哪里出错了。

4

3 回答 3

2

这是因为 ngOnInit() 方法在创建组件期间只调用一次。当您单击实验 2 时,您不会创建新的实验组件。你只用旧的。

Url 正在更改,因为您仍然订阅了路由参数。但是您的 Service 调用不在 Observable 范围内。所以只需将服务调用放入您的 oberable 中,然后每次更改路由参数时,它都会加载新数据。

ngOnInit() {

    Observable.combineLatest(this.route.parent.params, this.route.parent.parent.params)
      .forEach((params: Params[]) => {
        this.experimentId = params[0]['id'];
        this.goalId = params[1]['id'];

        console.log('Experiment ID: ' + this.experimentId + '| Goal Id: ' + this.goalId);
        this.notes$ = this.experimentsService.findAllNotesForExperiment(this.experimentId);
      });
于 2016-11-23T10:59:46.737 回答
2

API 在最新版本angular 5.2.5中发生了很大变化 正如 Emre 所说,问题是 ngOnInit 在第一次创建子组件时只被调用一次,在创建后需要通知组件对 url 的更改,以便它可以再次获取参数,这可以通过在路由器对象上添加一个侦听器然后使用路由对象来获取所需的部分来完成。以下是一些基于英雄之旅示例应用程序的示例代码:

import {Component, Input, OnInit} from '@angular/core';
import {Hero} from '../hero';
import {HeroService} from "../hero.service";
import {ActivatedRoute, Router} from "@angular/router"; //Import Router and ActivatedRoute classes
import {Location} from '@angular/common';
import {MessageService} from "../message.service";

@Component({
  selector: 'app-hero-detail',
  templateUrl: './hero-detail.component.html',
  styleUrls: ['./hero-detail.component.css']
})
export class HeroDetailComponent implements OnInit {
  @Input() hero: Hero;

  constructor(private route: ActivatedRoute,
              private heroService: HeroService,
              private messageService: MessageService,
              private location: Location,
              private router: Router) {
  }

  ngOnInit(): void {
    this.router.events.subscribe((val) => {//Use Router class to subscribe to events
      const id = +this.route.snapshot.paramMap.get('id');//When a route event occurs use the active route to update the parameter needed
      this.getHero(id);//Do what you would have initially done with the url value
    });
  }

  getHero(id): void {
    this.messageService.add(`HeroDetailComponent: fetching hero: ${id}`);
    this.heroService.getHero(id)
      .subscribe(hero => this.hero = hero);
  }

  goBack(): void {
    this.location.back();
  }
}

最相关的部分在ngOnInit()

于 2018-02-22T08:33:20.967 回答
0

激活路由具有父属性。只需订阅子组件中的参数,如下所示:

this.route.parent.params.subscribe((params: Params) => {
  // some stuff
});
于 2020-09-30T15:10:22.500 回答