Angular: 如何根据父应用组件的路由变化重新渲染子组件?
Angular: How to re-render a child component based on route change of parent app component?
我的应用呈现一个项目组件,其中包含来自 URL 的给定 ID 的信息,例如 my.app/project/foo
。
应用组件:
- 使用
<router-outlet>
渲染项目组件
- 包含所有项目的列表以便导航到每个项目
问题是:当你点击一个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 组件应该 "trigger" 项目组件的新渲染,或者可能将 url 中的 id 参数作为 "input" 到项目组件 ... 或 ...
- 项目 组件应该以不同于我当前使用路由快照实现的方式监听路由变化。
你怎么看?
你应该分开你的路线,这样 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);
);
}
耶!
我的应用呈现一个项目组件,其中包含来自 URL 的给定 ID 的信息,例如 my.app/project/foo
。
应用组件:
- 使用
<router-outlet>
渲染项目组件 - 包含所有项目的列表以便导航到每个项目
问题是:当你点击一个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 组件应该 "trigger" 项目组件的新渲染,或者可能将 url 中的 id 参数作为 "input" 到项目组件 ... 或 ...
- 项目 组件应该以不同于我当前使用路由快照实现的方式监听路由变化。
你怎么看?
你应该分开你的路线,这样 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);
);
}
耶!