使用 Angular Router 原生设置页面标题🔥
使用 Angular 构建应用程序时,一个常见的做法是在每次成功导航后更新页面标题。这有助于提高可访问性并改善导航体验。过去,您必须手动执行此操作,但 Angular Router 14 版本中新增的一项功能可以原生处理此操作,同时允许您自定义其行为。本文将向您展示如何使用 Angular Router 的这项新内置功能在每次成功导航后设置页面标题。
使用路由器事件设置页面标题♻️
以前,每次导航成功后,使用 Angular 路由器设置页面标题都需要在每个项目中单独添加代码,或者使用 Angular 库(如果提供)。以下示例代码展示了如何执行此操作:
首先,您将使用对象data
中的属性Route
和title
键来设置页面的标题。
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AboutComponent } from './about.component';
import { HomeComponent } from './home.component';
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
data: { title: 'Home' }
},
{
path: 'about',
component: AboutComponent,
data: { title: 'About Me' }
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
AppComponent
接下来,您将向您的或其他根级服务添加代码,以监听来自 Angular Router 的事件,查找title
路由上的属性,并使用它来设置页面标题。
import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { filter, map } from 'rxjs';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
constructor(
private router: Router,
private titleService: Title
) {}
ngOnInit() {
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => {
let route: ActivatedRoute = this.router.routerState.root;
let routeTitle = '';
while (route!.firstChild) {
route = route.firstChild;
}
if (route.snapshot.data['title']) {
routeTitle = route!.snapshot.data['title'];
}
return routeTitle;
})
)
.subscribe((title: string) => {
if (title) {
this.titleService.setTitle(`My App - ${title}`);
}
});
}
}
您必须将相同的代码复制到您处理的每个项目中。现在,让我们看看页面标题如何与 Angular Router 原生协作。
使用内置的 TitleStrategy 🤩
在 Angular v14 中,有一个内置的策略服务,用于根据主路由器出口从路由收集标题,并设置浏览器的页面标题。
您无需使用data
带有键的对象,而是可以在路由对象本身上title
添加一个新属性来设置页面标题。title
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { AboutComponent } from './about.component';
import { HomeComponent } from './home.component';
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
title: "'My App - Home' // <-- Page title"
},
{
path: 'about',
component: AboutComponent,
title: "'My App - About Me' // <-- Page title"
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
现在,您可以从监听路由器事件中删除所有自定义代码AppComponent
。👏
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {}
就是这样!现在,当您成功导航到每个路由时,页面标题将更新为每个路由中定义的标题。
需要注意的是,目前没有办法为每个路由定义一个前缀,例如My App
。在较大的应用程序中,这可能会导致页面标题设置重复和不一致。
这就是您使用自定义标题策略的地方。
覆盖全局标题策略✍️
Angular Router 还提供了一个抽象TitleStrategy
类,您可以使用它来扩展所提供的默认服务的功能。
TitleStrategy
首先,从包中导入类@angular/router
。
import { Injectable, NgModule } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { RouterModule, RouterStateSnapshot, Routes, TitleStrategy } from '@angular/router';
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
title: 'Home'
},
{
path: 'about',
component: AboutComponent,
title: 'About Me'
}
];
接下来,扩展该类以实现自定义页面标题策略,该策略采用从构建的标题routerState
并将其作为应用程序名称的前缀。
@Injectable()
export class TemplatePageTitleStrategy extends TitleStrategy {
constructor(private readonly title: Title) {
super();
}
override updateTitle(routerState: RouterStateSnapshot) {
const title = this.buildTitle(routerState);
if (title !== undefined) {
this.title.setTitle(`My App - ${title}`);
}
}
}
接下来,提供TemplatePageTitleStrategy
作为默认的覆盖TitleStrategy
。
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
providers: [
{
provide: TitleStrategy,
useClass: TemplatePageTitleStrategy
}
]
})
export class AppRoutingModule {}
现在每个路由仅提供页面标题本身,并且整个应用程序的前缀仅在一个地方使用。
使用解析器设置页面标题🤖
解析器是 Angular 路由器中一个熟悉的概念。您通常使用它们在路由加载之前获取数据。您还可以使用解析器动态获取单个路由的页面标题。
下面的示例使用CustomTitleResolver
来定义/about
路线的标题。
import { Injectable, NgModule } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { RouterModule, RouterStateSnapshot, Routes, TitleStrategy } from '@angular/router';
@Injectable({ providedIn: 'root' })
export class CustomTitleResolver {
resolve() {
return Promise.resolve('Custom About Me');
}
}
const routes: Routes = [
{
path: 'home',
component: HomeComponent,
title: 'Home'
},
{
path: 'about',
component: AboutComponent,
title: CustomTitleResolver
}
];
标题解析器可以像任何其他解析器一样使用,允许您注入依赖项、执行某些逻辑或返回可观察对象或返回页面标题字符串的 Promise。
摘要🪄
新的标题策略通过人们长期要求的 Angular Router 提供了更多开箱即用的功能,并为开发人员提供了以自定义方式处理页面标题的更多灵活性。
GitHub 仓库:https://github.com/brandonroberts/angular-router-page-titles
如果你喜欢这篇文章,请点击❤️,让其他人也看到。在 Twitter 上关注我,并订阅我的YouTube 频道,获取更多关于Angular、NgRx等内容!
文章来源:https://dev.to/brandontroberts/setting-page-titles-natively-with-the-angular-router-393j