Angular: 如何根据父应用组件的路由变化重新渲染子组件?

Angular: How to re-render a child component based on route change of parent app component?

我的应用呈现一个项目组件,其中包含来自 URL 的给定 ID 的信息,例如 my.app/project/foo

应用组件:

问题是:当你点击一个link时,路由会随着项目id正确改变,但是项目组件不会根据新的id再次重新渲染。重新加载项目组件后正确呈现,但不是在单击另一个 id 之后。

app.routing.module.ts:

const routes: Routes = [
...
  {
    path: 'project/:key',
    loadChildren: () =>
      import('../project-page/project-page.module').then(
        m => m.ProjectPageModule
      )
  }
...
];

app.component.html:

<a routerLink="/project/{{ project.id }}" *ngFor="let project of projects">
  {{ project.name }}
</a>
...
<div class="content">
  <router-outlet></router-outlet>
</div>

项目-page.component.ts(在 ProjectPageModule 内):

export class ProjectPageComponent implements OnInit {

  project: any;

  ngOnInit(): void {
    const id = this.route.snapshot.paramMap.get('id');

    return this.projectService
      .getProjectById(id)
      .pipe(delay(1000) /* debug only */)
      .subscribe(response => this.project = response);
    );
  }
  ...
}

项目-page.component.html:

<h1>{{ project.id }}</h1>

我不确定

你怎么看?

你应该分开你的路线,这样 app.routing.module 只包含:

const routes: Routes = [
...
  {
    path: 'project',
    loadChildren: () =>
      import('../project-page/project-page.module').then(m => m.ProjectPageModule)
  }
...
];

然后创建另一个路由模块,例如 project-page.routing.module 并将其导入到您的 ProjectPageModule 中。您的子模块的路由可以这样定义:

const appRoutes: Routes = [
    {
        path: '',
        component: ProjectPageEntryComponent,
        children: [
            {
                path: ':id',
                component: ProjectPageComponent
            }
        ]
    }
];

@NgModule({
    imports: [RouterModule.forChild(appRoutes)],
    exports: [RouterModule]
})
export class ProjectPageRoutingModule {}

最后 ProjectPageEntryComponent 的代码将是这样的:

@Component({
    template: '<router-outlet></router-outlet>'
})
export class ProjectPageEntryComponent {}

这样您就可以在主 app.routing.module 中只处理高级导航,而在其单独的文件中处理任何 SpecificModule 相关导航的更具体导航。

我想到的解决方案是子组件需要在其ngOnInit方法中监听路由变化:

  ngOnInit(): void {
    this.route.params.subscribe((param) => {
      this.getProjectFromUrl(param.id);
    });
  }

  getProjectFromUrl(id: number): any {
    return this.projectService
      .getProjectById(id)
      .pipe(delay(1000) /* debug only */)
      .subscribe(response => this.project = response);
    );
  }

耶!