在 Angular 中将路由逻辑与组件逻辑分开
Separate routing logic from component logic in Angular
我正在努力学习 Angular,我在路由方面遇到了关注点分离问题。在我发现的所有指南中,发生的情况是您在路由模块中指定路由和参数,但在组件文件中解析它们。比如在经典的英灵之旅例子中:
// in app-routing.module.ts
{ path: 'hero/:id': component: HeroDetailComponent }
// in hero-detail.component.ts
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location
) {}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
但在本教程的前面,您所拥有的是 Hero
对象被用作 Input()
:
@Input() hero: Hero;
然后您将绑定到它:
<hero-detail [hero]='hero'></hero-detail>
我想要的是能够保留该逻辑,而不是解析 URL 并在与路由模块相同的文件中传递 Input()
s,并保留组件文件原样。类似于:
// app-routing.module.ts
{
path: 'hero/:id', component: HeroDetailComponent, inputs: path => ({ hero: getHeroObject(+path.params["id"]) })
}
Angular 路由中是否有任何选项可以做这样的事情?如果没有,你能想出一种迂回的方式来分离逻辑部分吗?我想到的一件事是在路由模块中为每个路径创建单独的组件,每个组件都呈现 "pure-logic" 组件,例如:
// app-routing/hero-detail-route.component.ts
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location
) {}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
<!--- app-routing/hero-detail-route.component.html -->
<hero-detail [hero]='hero'></hero-detail>
但这只是一种 "kicking the problem down the road",不是吗?
有什么想法吗?
提前致谢!
您可以通过两种方式完成。
1.使用 resolvers
你可以像
一样在路由中附加解析器
{
path: 'hero/:id',
component: HeroDetailComponent,
resolve: {
hero: HeroDetailResolver
}
}
HeroDetailResolver
将包含从服务器获取英雄详细信息的所有逻辑。在 component
中,您捕获解析器数据。
this.route.data.subscribe(data => {
this.hero = data.hero;
});
如果您不熟悉 angular resolvers
,它们是一个方便的工具,可以在 component
加载之前预取一些服务器数据。
2。使用 smart parent
和 dumb child
组件
使用smart parent component
获取所有服务器数据并将它们提供给dumb child components
。在这种情况下,您可以使用 HeroDetailLayoutComponent
来获取英雄详细信息。然后将其作为 @Input()
传递给 HeroDetailComponent
.
// in app-routing.module.ts
{ path: 'hero/:id': component: HeroDetailLayoutComponent }
// in hero-detail-layout.component.ts
constructor(private route: ActivatedRoute, private heroService: HeroService) {}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id).subscribe(hero => this.hero = hero);
}
// hero-detail-layout.component.html
<hero-detail [hero]='hero'></hero-detail>
// in hero-detail.component.ts
@Input() hero: any[];
我正在努力学习 Angular,我在路由方面遇到了关注点分离问题。在我发现的所有指南中,发生的情况是您在路由模块中指定路由和参数,但在组件文件中解析它们。比如在经典的英灵之旅例子中:
// in app-routing.module.ts
{ path: 'hero/:id': component: HeroDetailComponent }
// in hero-detail.component.ts
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location
) {}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
但在本教程的前面,您所拥有的是 Hero
对象被用作 Input()
:
@Input() hero: Hero;
然后您将绑定到它:
<hero-detail [hero]='hero'></hero-detail>
我想要的是能够保留该逻辑,而不是解析 URL 并在与路由模块相同的文件中传递 Input()
s,并保留组件文件原样。类似于:
// app-routing.module.ts
{
path: 'hero/:id', component: HeroDetailComponent, inputs: path => ({ hero: getHeroObject(+path.params["id"]) })
}
Angular 路由中是否有任何选项可以做这样的事情?如果没有,你能想出一种迂回的方式来分离逻辑部分吗?我想到的一件事是在路由模块中为每个路径创建单独的组件,每个组件都呈现 "pure-logic" 组件,例如:
// app-routing/hero-detail-route.component.ts
constructor(
private route: ActivatedRoute,
private heroService: HeroService,
private location: Location
) {}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
<!--- app-routing/hero-detail-route.component.html -->
<hero-detail [hero]='hero'></hero-detail>
但这只是一种 "kicking the problem down the road",不是吗?
有什么想法吗?
提前致谢!
您可以通过两种方式完成。
1.使用 resolvers
你可以像
一样在路由中附加解析器{
path: 'hero/:id',
component: HeroDetailComponent,
resolve: {
hero: HeroDetailResolver
}
}
HeroDetailResolver
将包含从服务器获取英雄详细信息的所有逻辑。在 component
中,您捕获解析器数据。
this.route.data.subscribe(data => {
this.hero = data.hero;
});
如果您不熟悉 angular resolvers
,它们是一个方便的工具,可以在 component
加载之前预取一些服务器数据。
2。使用 smart parent
和 dumb child
组件
使用smart parent component
获取所有服务器数据并将它们提供给dumb child components
。在这种情况下,您可以使用 HeroDetailLayoutComponent
来获取英雄详细信息。然后将其作为 @Input()
传递给 HeroDetailComponent
.
// in app-routing.module.ts
{ path: 'hero/:id': component: HeroDetailLayoutComponent }
// in hero-detail-layout.component.ts
constructor(private route: ActivatedRoute, private heroService: HeroService) {}
ngOnInit() {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id).subscribe(hero => this.hero = hero);
}
// hero-detail-layout.component.html
<hero-detail [hero]='hero'></hero-detail>
// in hero-detail.component.ts
@Input() hero: any[];