我有一个看似简单的问题。我有一个标题组件,我想在其中显示当前活动路线的标题。为此,我将 ActivatedRoute 注入标题组件中,并尝试显示路由标题,如下所示:
export class HeaderComponent {
public title$;
constructor(private route: ActivatedRoute) {
this.title$ = route.title;
}
}
以及组件的html
<header>
<h1>My Website - {{ title$ | async }}</h1>
</header>
不知怎的,这不起作用。但我可以看到我在不同路由中定义的标题会更新浏览器窗口标题。
您的标头组件似乎在您的 ShellComponent 中使用,我想您的路由配置感觉如下所示:
const routes: Route[] = [
{
path: '',
component: ShellComponent, // <-- Header component is used here
children: [ // might be load children
{ path: 'route1', title: 'My title', component: ...}, // <-- title is here
...
]
}
]
因此,如果这是正确的,那么您可以看到 Header 组件位于定义了标题的路由上方的路由/注入器/组件树中。
当您在 HeaderComponent 中注入 ActivatedRoute 时,您将获得此包装器的路由实例
{
path: '',
component: ShellComponent,
它没有标题,所以你会得到它
undefined
。
您可以做的是,如果您没有多路由器出口结构,那么您可以手动深入路由树以获取最多子路由。像这样的东西
constructor(private route: ActivatedRoute) {}
get leaf(): ActivatedRoute {
let leaf = this.route;
while (leaf.firstChild) {
leaf = leaf.firstChild;
}
return leaf;
}
并在模板中执行
{{leaf.title | async}}
您应该小心组件上的变更检测策略。
每当更改检测到此组件时,您的
get leaf()
就会被执行,但如果您有OnPush
,您将必须标记您的组件,以便在手动更改路由时进行检查。例如,您可以监听 router.events,每当有 NavigationEnd
事件时,执行 markForCheck
来更新它。
或者你可以做一个混合版本以使其与 OnPush 一起使用
#route = inject(ActivatedRoute);
#router = inject(Router);
title$ = this.#router.events.pipe(
filter((evt) => evt instanceof NavigationEnd),
startWith(null),
switchMap(() => this.leaf.title)
);
get leaf(): ActivatedRoute {
let leaf = this.#route;
while (leaf.firstChild) {
leaf = leaf.firstChild;
}
return leaf;
}
并在模板中使用
{{title$ | async}}
所以最终的解决方案取决于您的变更检测策略设置
工作结果:https://stackblitz.com/edit/stackblitz-starters-ca3d4z?file=src%2Fmain.ts