如何在angular2路由器中更改页面标题



我正试图从路由器更改页面标题,这可以做到吗?

import {RouteConfig} from 'angular2/router';
@RouteConfig([
{path: '/home', component: HomeCmp, name: 'HomeCmp' }
])
class MyApp {}

Title服务@EricMartinez指出有一个setTitle()方法-这是所有你需要设置标题。

在路由更改时自动执行,截至目前没有内置的方法可以做到这一点,除了订阅Router并在回调中调用setTitle():

import {RouteConfig} from 'angular2/router';
import {Title} from 'angular2/platform/browser';
@RouteConfig([
{path: '/home', component: HomeCmp, name: 'HomeCmp' }
])
class MyApp {
constructor(router:Router, title:Title) {
router.events.subscribe((event)=>{ //fires on every URL change
title.setTitle(getTitleFor(router.url));
});
}
}

也就是说,我现在强调,因为路由器仍在大量开发中,我希望(或至少希望)我们能够在最终版本中通过RouteConfig实现这一点。

编辑:

从Angular 2(2.0.0)发布开始,有了一些变化:

  • Title服务的文档现在在这里:https://angular.io/docs/ts/latest/api/platform-browser/index/Title-class.html
  • 业务从'@angular/platform-browser'
  • 导入

这是我的方法,工作得很好,特别是对于嵌套路由:

我使用递归助手方法来获取路由更改后最深层的可用标题:

@Component({
selector: 'app',
template: `
<h1>{{title | async}}</h1>
<router-outlet></router-outlet>
`
})
export class AppComponent {
constructor(private router: Router) {
this.title = this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.getDeepestTitle(this.router.routerState.snapshot.root));
}
title: Observable<string>;
private getDeepestTitle(routeSnapshot: ActivatedRouteSnapshot) {
var title = routeSnapshot.data ? routeSnapshot.data['title'] : '';
if (routeSnapshot.firstChild) {
title = this.getDeepestTitle(routeSnapshot.firstChild) || title;
}
return title;
}
}

这是假设你在你的路由的data属性中分配了页面标题,像这样:

{
path: 'example',
component: ExampleComponent,
data: {
title: 'Some Page'
}
}

角4 +:

如果你想使用路由自定义数据来为每个路由路径定义页面标题,下面的方法将适用于嵌套路由和angular版本4+:

你可以在你的路由定义中传递页面标题:

{path: 'home', component: DashboardComponent, data: {title: 'Home Pag'}},
{path: 'about', component: AboutUsComponent, data: {title: 'About Us Page'}},
{path: 'contact', component: ContactUsComponent, data: {title: 'Contact Us Pag'}},

现在,最重要的在你的上层组件(如AppComponent)中,你可以全局捕获路由自定义数据在每次路由更改和更新页面标题:

import {Title} from "@angular/platform-browser";
import { filter, map } from 'rxjs/operators';
export class AppComponent implements OnInit {
constructor(
private activatedRoute: ActivatedRoute, 
private router: Router, 
private titleService: Title
) { }
ngOnInit() {
this.router
.events.pipe(
filter(event => event instanceof NavigationEnd),
map(() => {
let child = this.activatedRoute.firstChild;
while (child) {
if (child.firstChild) {
child = child.firstChild;
} else if (child.snapshot.data && child.snapshot.data['title']) {
return child.snapshot.data['title'];
} else {
return null;
}
}
return null;
})).subscribe( (title: any) => {
this.titleService.setTitle(title);
});
}

上面的代码是在angular版本4+上测试的。

这真的很容易做到,您可以按照以下步骤查看立即效果:

我们在bootstrap中提供Title服务:
import { NgModule } from '@angular/core';
import { BrowserModule, Title }  from '@angular/platform-browser';
import { AppComponent } from './app.component';
@NgModule({
imports: [
BrowserModule
],
declarations: [
AppComponent
],
providers: [
Title
],
bootstrap: [ AppComponent ]
})
export class AppModule { }

然后在你想要的组件中导入这个服务:

import { Component } from '@angular/core';
import { Title }     from '@angular/platform-browser';
@Component({
selector: 'my-app',
template:
`<p>
Select a title to set on the current HTML document:
</p>
<ul>
<li><a (click)="setTitle( 'Good morning!' )">Good morning</a>.</li>
<li><a (click)="setTitle( 'Good afternoon!' )">Good afternoon</a>.</li>
<li><a (click)="setTitle( 'Good evening!' )">Good evening</a>.</li>
</ul>
`
})
export class AppComponent {
public constructor(private titleService: Title ) { }
public setTitle( newTitle: string) {
this.titleService.setTitle( newTitle );
}
}

现在点击这些链接来查看标题的变化。

你也可以使用ng2-meta来更改页面标题和描述,你可以参考这个链接:

https://github.com/vinaygopinath/ng2-meta

Angular 2提供了一个Title Service,参见Shailesh的答案只是对该代码的复制。

我们的app.module.ts

import { BrowserModule, Title } from '@angular/platform-browser';
........
providers: [..., Title],
bootstrap: [AppComponent]
现在移动到我们的app.component.ts
import { Title }     from '@angular/platform-browser';
......
export class AppComponent {
public constructor(private titleService: Title ) { }
public setTitle( newTitle: string) {
this.titleService.setTitle( newTitle );
}
}

把标题标签放在你的组件html上,它会为你读取和设置。

如果您想知道如何动态设置它并了解更多细节,请参阅本文

import {Title} from "@angular/platform-browser"; 
@Component({
selector: 'app',
templateUrl: './app.component.html',
providers : [Title]
})
export class AppComponent implements {
constructor( private title: Title) { 
this.title.setTitle('page title changed');
}
}

我是这样做的:

constructor(private router: Router, private title: Title) { }
ngOnInit() {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
this.title.setTitle(this.recursivelyGenerateTitle(this.router.routerState.snapshot.root).join(' - '));
}
});
}
recursivelyGenerateTitle(snapshot: ActivatedRouteSnapshot) {
var titleParts = <string[]>[];
if (snapshot) {
if (snapshot.firstChild) {
titleParts = titleParts.concat(this.recursivelyGenerateTitle(snapshot.firstChild));
}
if (snapshot.data['title']) {
titleParts.push(snapshot.data['title']);
}
}
return titleParts;
}

角6 +我已经使用新的Pipe()修改了旧代码,它工作得很好。

import { Title } from '@angular/platform-browser';
import { filter, map, mergeMap } from 'rxjs/operators';

constructor(
private router: Router,
public activatedRoute: ActivatedRoute,
public titleService: Title,
) {
this.setTitle();
}

setTitle() {
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map((route: any) => {
while (route.firstChild) route = route.firstChild;
return route;
}),
filter((route) => route.outlet === 'primary'),
mergeMap((route: any) => route.data)).subscribe((event) => {
this.titleService.setTitle(event['title']);
console.log('Page Title', event['title']);
})
}

这是在页面/视图被导航时改变页面标题的最简单方法(从Angular @2.3.1开始测试)。只需将以下解决方案应用到所有视图中,就可以了:

About Us页面/view示例代码:

import {Title} from "@angular/platform-browser";
export class AboutUsComponent implements OnInit {
constructor(private _titleService: Title) {
}
ngOnInit() {
//Set page Title when this view is initialized
this._titleService.setTitle('About Us');
}
}

联系我们页面/视图示例代码:

import {Title} from "@angular/platform-browser";
export class ContactusComponent implements OnInit {
constructor(private _titleService: Title) {
}
ngOnInit() {
//Set page Title
this._titleService.setTitle('Contact Us');
}
}

在下面的例子中:

-我们为任何路由对象添加了data: {title: 'NAME'}的对象。

-我们为上传时间设置了一个基本名称("CTM")(当按F5刷新…):<title>CTM</title>.

-我们添加了"TitleService"类。

-我们通过从app.component.ts中过滤其他事件来处理它们。

index . html:

<!DOCTYPE html>
<html>
<head>
<base href="/">
<title>CTM</title>
</head>

app.module.ts:

import { NgModule, enableProdMode } from '@angular/core';
import { BrowserModule  } from '@angular/platform-browser';
import { TitleService }   from './shared/title.service';
...

@NgModule({
imports: [
BrowserModule,
..
],
declarations: [
AppComponent,
...
],
providers: [
TitleService,
...
],
bootstrap: [AppComponent],
})
export class AppModule { }
enableProdMode();

title.service.ts:

import { Injectable } from '@angular/core';
import { Title }  from '@angular/platform-browser';
import { ActivatedRouteSnapshot } from '@angular/router';

@Injectable()
export class TitleService extends Title {
constructor() {
super();
}

private recursivelyGenerateTitle(snapshot: ActivatedRouteSnapshot) {
var titleParts = <string[]>[];
if (snapshot) {
if (snapshot.firstChild) {
titleParts = this.recursivelyGenerateTitle(snapshot.firstChild);
}
if (snapshot.data['title']) {
titleParts.push(snapshot.data['title']);
}
}
return titleParts;
}
public CTMGenerateTitle(snapshot: ActivatedRouteSnapshot) {
this.setTitle("CTM | " + this.recursivelyGenerateTitle(snapshot).join(' - '));
}
}

app-routing.module.ts:

import { Injectable } from '@angular/core';
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { MainComponent } from './components/main.component';
import { Router, CanActivate } from '@angular/router';
import { AuthGuard }          from './shared/auth/auth-guard.service';
import { AuthService }    from './shared/auth/auth.service';

export const routes: Routes = [
{ path: 'dashboard', component: MainComponent, canActivate: [AuthGuard], data: { title: 'Main' } },
];
@NgModule({
imports: [
RouterModule.forRoot(routes, { useHash: true })  // .../#/crisis-center/
],
exports: [RouterModule],
providers: [
..
]
})
export class AppRoutingModule { }
export const componentsOfAppRoutingModule = [MainComponent];

app.component.ts:

import { Component } from '@angular/core';
import { Router, NavigationEnd, ActivatedRouteSnapshot } from '@angular/router';
import { TitleService } from './shared/title.service';
@Component({
selector: 'ctm-app',
template: `
<!--<a [routerLink]="['/dashboard']">Dashboard</a>
<a [routerLink]="['/login']">Login</a>
<a [routerLink]="['/']">Rooting</a>-->
<router-outlet></router-outlet>
`
})
export class AppComponent {
constructor(private router: Router, private titleService: TitleService) {
this.router.events.filter((event) => event instanceof NavigationEnd).subscribe((event) => {
console.log("AppComponent.constructor: Setting HTML document's Title");
this.titleService.CTMGenerateTitle(this.router.routerState.snapshot.root);
});
}

}

在Angular 6和6+中使用Pipe和map方法可以正常工作,而不是使用filter

Step1: routing setup

{path: 'dashboard', component: DashboardComponent, data: {title: 'My Dashboard'}},
{path: 'aboutUs', component: AboutUsComponent, data: {title: 'About Us'}},
{path: 'contactUs', component: ContactUsComponent, data: {title: 'Contact Us Page'}},

步骤2:在app.module.ts中导入module

import { BrowserModule, Title } from '@angular/platform-browser';

then in provider add providers:[title]

步骤3在主组件中导入

import { Title } from "@angular/platform-browser";
import { RouterModule, ActivatedRoute, Router, NavigationEnd } from "@angular/router";
import { filter, map } from 'rxjs/operators';
constructor(private titleService: Title, private router: Router, private activatedRoute: ActivatedRoute) {
}
ngOnInit() {
this.router.events.pipe(map(() => {
let child = this.activatedRoute.firstChild;
while (child) {
if (child.firstChild) {
child = child.firstChild;
} else if (child.snapshot.data && child.snapshot.data['title']) {
return child.snapshot.data['title'];
} else {
return null;
}
}
return null;
})).subscribe(title => {
this.titleService.setTitle(title);
});
}

我还可以推荐我刚刚发布的@ngx-meta/core plugin插件,如果你正在寻找一种方法来动态设置页面标题和元标签。

角6 +

如果路由配置如下:

Routes = [
{  path: 'dashboard',
component: DashboardComponent,
data: {title: 'Dashboard'}
}]

**那么在组件构造函数中,标题可以这样设置:- **

constructor( private _titleService: Title, public activatedRoute: ActivatedRoute) {
activatedRoute.data.pipe(map(data => data.title)).subscribe(x => this._titleService.setTitle(x));
}

设置标题的简单通用方法:

import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private titleService: Title
) {}
ngOnInit() {
this.router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
const { title } = this.activatedRoute.firstChild.snapshot.data;
this.titleService.setTitle(title);
}
});
}
}

需要在每条路由上设置title,如:

{ path: '', component: WelcomeComponent, data: {title: 'Welcome to my app'} }

简单,如果你使用的是AngularVersion>14.0你可以简单地把title放到Routes数组中,比如-

const routes: Routes = [
{
path: 'home',
component: HomeComponent,
title: "'My App - Home' // <-- Page title"
},
{
path: 'about',
component: AboutComponent,
title: "'My App - About Me'  // <-- Page title"
}
];

最新更新