使用 Angular 路由器本地设置页面标题?

发表:2年前 更新:2年前

使用 Angular 构建应用程序时,您应该做的一件常见事情是在每次成功导航后更新页面标题。这有助于可访问性并改善导航体验。这是您过去必须手动执行的操作,但最近添加到版本 14 中的 Angular 路由器的一项功能可以本地处理此问题,同时允许您自定义其行为。这篇文章向您展示了如何在每次成功导航后使用 Angular 路由器的新内置功能来设置页面标题。

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

以前,在每次成功导航后使用 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 路由器的事件,查找 title 路由上的属性,并使用它来设置页面标题。

import { Component } from '@angular /core';
import { Title } from '@angular /platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular /router';
import { filter, map } from 'rxjs';

@Com ponent({
  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 路由器一起工作的方式。


使用内置的 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: AboutComponent,
    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';

@Com ponent({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {}

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

需要注意的一点是,没有办法为每个路由定义前缀,例如 My App. 在较大的应用程序中,这可能会导致设置页面标题的重复和不一致。

这就是您将使用自定义标题策略的地方。


覆盖全球标题策略 ✍️

Angular 路由器还提供了一个抽象 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: AboutComponent,
    title: 'Home'
  },
  {
    path: 'about',
    component: AboutComponent,
    title: 'About Me'
  }
];

接下来,您扩展该类以实现自定义页面标题策略,该策略采用从 构建的标题 routerState 并在其前面加上应用程序名称。

@Injectable()
ex port 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 路由器的一个熟悉的概念。您通常在加载路线之前使用它们来获取数据。您还可以使用解析器动态获取单个路由的页面标题。

下面的示例使用 a 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: AboutComponent,
    title: 'Home'
  },
  {
    path: 'about',
    component: AboutComponent,
    title: CustomTitleResolver
  }
];

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

总结 ?

新的标题策略为 Angular 路由器提供了更多开箱即用的功能,这是长期以来一直要求的,并为开发人员以自定义方式处理页面标题提供了更大的灵活性。

signature
保持理智
评论

无权限

请登录后评论

RunPod公众号

赞助商

联系我们

QQ群:798695907

邮箱:laravel@88.com