使用 Angular Router 原生设置页面标题🔥

2025-06-04

使用 Angular Router 原生设置页面标题🔥

使用 Angular 构建应用程序时,一个常见的做法是在每次成功导航后更新页面标题。这有助于提高可访问性并改善导航体验。过去,您必须手动执行此操作,但 Angular Router 14 版本中新增的一项功能可以原生处理此操作,同时允许您自定义其行为。本文将向您展示如何使用 Angular Router 的这项新内置功能在每次成功导航后设置页面标题。

使用路由器事件设置页面标题♻️

以前,每次导航成功后,使用 Angular 路由器设置页面标题都需要在每个项目中单独添加代码,或者使用 Angular 库(如果提供)。以下示例代码展示了如何执行此操作:

首先,您将使用对象data中的属性Routetitle键来设置页面的标题。

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 { }
Enter fullscreen mode Exit fullscreen mode

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}`);
        }
      });
  }
}
Enter fullscreen mode Exit fullscreen mode

您必须将相同的代码复制到您处理的每个项目中。现在,让我们看看页面标题如何与 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 { }
Enter fullscreen mode Exit fullscreen mode

现在,您可以从监听路由器事件中删除所有自定义代码AppComponent。👏

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {}
Enter fullscreen mode Exit fullscreen mode

就是这样!现在,当您成功导航到每个路由时,页面标题将更新为每个路由中定义的标题。

需要注意的是,目前没有办法为每个路由定义一个前缀,例如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'
  }
];
Enter fullscreen mode Exit fullscreen mode

接下来,扩展该类以实现自定义页面标题策略,该策略采用从构建的标题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}`);
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

接下来,提供TemplatePageTitleStrategy作为默认的覆盖TitleStrategy

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [
    {
      provide: TitleStrategy,
      useClass: TemplatePageTitleStrategy
    }
  ]
})
export class AppRoutingModule {}
Enter fullscreen mode Exit fullscreen mode

现在每个路由仅提供页面标题本身,并且整个应用程序的前缀仅在一个地方使用。


使用解析器设置页面标题🤖

解析器是 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
  }
];
Enter fullscreen mode Exit fullscreen mode

标题解析器可以像任何其他解析器一样使用,允许您注入依赖项、执行某些逻辑或返回可观察对象或返回页面标题字符串的 Promise。

摘要🪄

新的标题策略通过人们长期要求的 Angular Router 提供了更多开箱即用的功能,并为开发人员提供了以自定义方式处理页面标题的更多灵活性。

GitHub 仓库:https://github.com/brandonroberts/angular-router-page-titles

如果你喜欢这篇文章,请点击❤️,让其他人也看到。在 Twitter 上关注我,并订阅我的YouTube 频道,获取更多关于AngularNgRx等内容!

文章来源:https://dev.to/brandontroberts/setting-page-titles-natively-with-the-angular-router-393j
PREV
最适合你的 React 项目的 Hooks
NEXT
使用 GitHub Copilot 构建 Angular 应用程序