我正在使用Angular 5构建一个小型宣传册类型的网站。到目前为止,我已经设置了路由,页面标题会根据激活的路由动态变化。我使用此博客上的说明进行了此操作:https://toddmotto.com/dynamic-page-titles-angular-2-router-events
我目前正在app.module.ts中存储我的路线和标题:
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
data: {
title: 'Home'
}
},
{
path: 'about',
component: AboutComponent,
data: {
title: 'About'
}
},
{
path: 'products-and-services',
component: ProductsServicesComponent,
data: {
title: 'Products & Services'
}
},
{
path: 'world-class-laundry',
component: LaundryComponent,
data: {
title: 'World Class Laundry'
}
},
{
path: 'contact',
component: ContactComponent,
data: {
title: 'Contact'
}
},
{
path: '**',
component: NotFoundComponent,
data: {
title: 'Page Not Found'
}
}
])
],
我想在那里存储我的元描述,如果在data:
下添加它们就足够了。
我正在使用以下代码提取该标题数据,该代码在上面的博客链接中注明:
ngOnInit() {
this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter((route) => route.outlet === 'primary')
.mergeMap((route) => route.data)
.subscribe((event) => {
this.titleService.setTitle(event['title']);
});
}
所以我的问题是,有没有办法使用相同的方法动态设置元描述?如果有一种方法来组合页面标题和元描述功能,那将是理想的。
我的角色训练非常有限,所以这可能是一个不起眼的问题。我更像是一个设计师/ css / html那种人。
答案 0 :(得分:30)
首先创建一个SEOService或类似下面的东西:
import {Injectable} from '@angular/core';
import { Meta, Title } from '@angular/platform-browser';
@Injectable()
export class SEOService {
constructor(private title: Title, private meta: Meta) { }
updateTitle(title: string) {
this.title.setTitle(title);
}
updateOgUrl(url: string) {
this.meta.updateTag({ name: 'og:url', content: url })
}
updateDescription(desc: string) {
this.meta.updateTag({ name: 'description', content: desc })
}
在组件中注入SEOService 后,在OnInit方法中设置元标记和标题
ngOnInit() {
this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.activatedRoute)
.map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter((route) => route.outlet === 'primary')
.mergeMap((route) => route.data)
.subscribe((event) => {
this._seoService.updateTitle(event['title']);
this._seoService.updateOgUrl(event['ogUrl']);
//Updating Description tag dynamically with title
this._seoService.updateDescription(event['title'] + event['description'])
});
}
编辑:对于使用管道运算符的RxJs 6+
ngOnInit() {
this.router.events.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
}),
filter((route) => route.outlet === 'primary'),
mergeMap((route) => route.data)
)
.subscribe((event) => {
this._seoService.updateTitle(event['title']);
this._seoService.updateOgUrl(event['ogUrl']);
//Updating Description tag dynamically with title
this._seoService.updateDescription(event['title'] + event['description'])
});
}
然后配置您的路线,如
{
path: 'about',
component: AboutComponent,
data: {
title: 'About',
description:'Description Meta Tag Content',
ogUrl: 'your og url'
}
},
恕我直言,这是一种处理元标记的明确方法。您可以更轻松地更新Facebook和Twitter特定标签。
答案 1 :(得分:6)
Title
和Meta
是Angular 4中引入的提供程序,并且应该在服务器端和客户端都执行此操作。
要创建或更新title
代码和description
元标记,请执行以下操作:
import { Meta, Title } from '@angular/platform-browser';
...
constructor(public meta: Meta, public title: Title, ...) { ... }
...
this.meta.updateTag({ name: 'description', content: description });
this.title.setTitle(title);
答案 2 :(得分:4)
Angular 6+和RxJS 6+解决方案,可在路线更改时动态设置标题
如果/当您升级到Angular 6时,这里就是解决方案。
此服务将:
将SEO /元服务创建/更改为以下内容。
(d)
导入您的服务并在构造器中调用它。
app.component.ts
import { Injectable } from '@angular/core';
import { Title, Meta } from '@angular/platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { filter, map, mergeMap } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class MetaService {
constructor(
private titleService: Title,
private meta: Meta,
private router: Router,
private activatedRoute: ActivatedRoute
) { }
updateMetaInfo(content, author, category) {
this.meta.updateTag({ name: 'description', content: content });
this.meta.updateTag({ name: 'author', content: author });
this.meta.updateTag({ name: 'keywords', content: category });
}
updateTitle(title?: string) {
if (!title) {
this.router.events
.pipe(
filter((event) => event instanceof NavigationEnd),
map(() => this.activatedRoute),
map((route) => {
while (route.firstChild) { route = route.firstChild; }
return route;
}),
filter((route) => route.outlet === 'primary'),
mergeMap((route) => route.data)).subscribe((event) => {
this.titleService.setTitle(event['title'] + ' | Site name');
});
} else {
this.titleService.setTitle(title + ' | Site name');
}
}
}
这仍然需要格式化这样的路由。
路由文件.ts
constructor(private meta: MetaService) {
this.meta.updateTitle();
}
希望这对您和其他希望在Angular 6中动态更新标题/元数据的人有所帮助。
答案 3 :(得分:1)
以下是我项目中的相关部分。 (角度2/4)
路线:
... const appRoutes: Routes = [
{
path: 'path1', loadChildren: './path1#path1Module',
data: {
title: '...',
description: '...',
keywords: '...'
}
},
{
path: 'path2', loadChildren: './path2#path2Module',
data: {
title: '...',
description: '...',
keywords: '...'
}
} ...
app.component.ts(或您的引导程序组件):
进口:
// imports
import { Component, OnInit} from '@angular/core';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/mergeMap';
import { Title,Meta } from '@angular/platform-browser';
构造函数:
// constructor:
constructor(private router: Router,
private route: ActivatedRoute,
private titleService: Title, private meta: Meta) {}
ngOnInit()方法:
ngOnInit() {
this.router.events
.filter((event) => event instanceof NavigationEnd)
.map(() => this.route)
.map((route) => {
while (route.firstChild) route = route.firstChild;
return route;
})
.filter((route) => route.outlet === 'primary')
.mergeMap((route) => route.data)
.subscribe((event) => {
this.updateDescription(event['description'], event['keywords'], event['title']);
});
}
更新标题和元标记->从ngOnInit()调用的方法:
updateDescription(desc: string, keywords: string, title: string) {
this.titleService.setTitle(title);
this.meta.updateTag({ name: 'description', content: desc })
this.meta.updateTag({ name: 'keywords', content: keywords })
this.meta.updateTag({ name: 'og:title', content: title })
this.meta.updateTag({ name: 'og:description', content: desc })
}
希望有帮助。
答案 4 :(得分:1)
由于Angular页面是在客户端渲染的,因此搜寻器无法检测到元标记。由于未检测到动态元标记,大多数爬网程序在运行时不执行javascript。即使对于Facebook和Twitter也是如此。
需要使用 Angular Universal进行服务器端渲染或预渲染服务,例如 prerender.io
答案 5 :(得分:1)
IMO 在 Routes 数组中使用数据(标题、描述等)不是那么一致,我们可以将所有数据聚合到一个地方。同样在 2021 年,我们可以开箱即用地使用常见的 Angular 工具:
seo-sitemap.ts
export const seoSitemap: ISitemapTag[] = [
{ customUrl: '/contact', title: null, description: 'Some description there', image: '/assets/path/to/image' },
{ customUrl: '/about', title: 'custom about title', description: 'Some description about', image: '/assets/path/to/another-image' }
];
export interface ISitemapTag {
customUrl: string;
title: string | null;
description: string | null;
image: string | null;
}
metatags.service.ts:
import { Injectable } from '@angular/core';
import { Meta, MetaDefinition, Title } from '@angular/platform-browser';
@Injectable()
export class MetatagsService {
constructor(private title: Title, private meta: Meta) {}
updateTitle(title: string) {
this.title.setTitle(title);
}
updateTag(tag: MetaDefinition) {
this.meta.updateTag(tag);
}
updateTags(tags: Array<MetaDefinition | null>) {
tags.forEach((tag) => {
tag && this.meta.updateTag(tag);
});
}
}
app.component.ts
import { MetatagsService } from './shared/services/metatags.service';
import { seoSitemap } from './seoSitemap';
constructor() {
this.sub = this.router.events.subscribe((event: Event) => {
if (event instanceof NavigationEnd) {
this.setMetaTags(event);
}
});
}
ngOnDestroy() { this.sub && this.sub.unsubscribe() }
private setMetaTags(event: NavigationEnd) {
const item = seoSitemap.find((i) => event.urlAfterRedirects === i.customUrl);
if (item) {
if (item.title) this.metatagsService.updateTitle(item.title);
this.metatagsService.updateTags([
item.description ? { name: 'description', content: item.description } : null,
item.image ? { name: 'image', content: item.image } : null,
]);
this.metatagsService.updateTag({ property: 'og:url', content: window.location.href });
} else {
this.metatagsService.updateTitle('Common title there');
}
}