如何在 angular 中添加规范 link 5
how to add canonical link in angular 5
如何在 angular 5 中动态添加规范 link
<link rel="canonical" href="http://foobar.com/gotcah"/>
我得到了解决方案,
创建 link 服务(例如:link.service.ts)并粘贴以下代码:
import { Injectable, Optional, RendererFactory2, ViewEncapsulation, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Injectable()
export class LinkService {
constructor(
private rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document
) {
}
/**
* Inject the State into the bottom of the <head>
*/
addTag(tag: LinkDefinition, forceCreation?: boolean) {
try {
const renderer = this.rendererFactory.createRenderer(this.document, {
id: '-1',
encapsulation: ViewEncapsulation.None,
styles: [],
data: {}
});
const link = renderer.createElement('link');
const head = this.document.head;
const selector = this._parseSelector(tag);
if (head === null) {
throw new Error('<head> not found within DOCUMENT.');
}
Object.keys(tag).forEach((prop: string) => {
return renderer.setAttribute(link, prop, tag[prop]);
});
// [TODO]: get them to update the existing one (if it exists) ?
renderer.appendChild(head, link);
} catch (e) {
console.error('Error within linkService : ', e);
}
}
private _parseSelector(tag: LinkDefinition): string {
// Possibly re-work this
const attr: string = tag.rel ? 'rel' : 'hreflang';
return `${attr}="${tag[attr]}"`;
}
}
export declare type LinkDefinition = {
charset?: string;
crossorigin?: string;
href?: string;
hreflang?: string;
media?: string;
rel?: string;
rev?: string;
sizes?: string;
target?: string;
type?: string;
} & {
[prop: string]: string;
};
在组件中导入服务:
import { LinkService } from '../link.service';
constructor(private linkService: LinkService) {
this.linkService.addTag( { rel: 'canonical', href: 'url here'} );
}
请参考下面link :
面对同样的问题,我四处搜索并找到了有关如何执行此操作的指南:
https://www.concretepage.com/angular/angular-title-service-and-canonical-url
虽然它使用的是 Angular 6,但我认为它向后兼容 5。
它基本上建议创建一个服务 (SEOService),以便在注入的任何地方创建规范 link。它将 Angular DOCUMENT
对象注入到服务中,并创建规范的 link 元素作为 HTMLLinkElement
.
注意解决方案 prerendering/serverside 呈现友好 - 因此,如果您希望更好地控制应用程序中页面的 SEO,我相信这就是您想要的。
这里是对文章中服务的最小重写:
seo.service.ts
import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class SeoService {
constructor(@Inject(DOCUMENT) private doc) {}
createLinkForCanonicalURL() {
let link: HTMLLinkElement = this.doc.createElement('link');
link.setAttribute('rel', 'canonical');
this.doc.head.appendChild(link);
link.setAttribute('href', this.doc.URL);
}
}
这里重写了使用该服务的组件:
data.component.ts
import { Component, OnInit } from '@angular/core';
import { SeoService } from './seo.service';
@Component({
selector: 'app-data',
templateUrl: './data.component.html'
})
export class DataComponent implements OnInit {
constructor(private seoService: SeoService) { }
ngOnInit() {
this.createLinkForCanonicalURL();
}
createLinkForCanonicalURL() {
this.seoService.createLinkForCanonicalURL();
}
}
您可以简单地让 createLinkForCanonicalURL()
方法采用 URL 的可选参数作为页面的规范参考,以实现完全控制。
如果您想动态添加规范 link 然后创建一个简单的 moveToHead 指令,如下所示:
@Directive({
selector: '[appMoveToHead]'
})
export class MoveToHeadDirective implements OnDestroy, OnInit {
constructor(private renderer: Renderer2,
private elRef: ElementRef,
@Inject(DOCUMENT) private document: Document) {
}
ngOnInit(): void {
this.renderer.appendChild(this.document.head, this.elRef.nativeElement);
this.renderer.removeAttribute(this.elRef.nativeElement, 'appmovetohead');
}
ngOnDestroy(): void {
this.renderer.removeChild(this.document.head, this.elRef.nativeElement);
}
}
在这里,当用户导航到另一个页面时,我们将从 DOM 中删除规范标签。我们在 MoveToHead 指令的 ngOnDestroy()
中执行此操作。因此,处理了新页面中存在先前规范标签的情况。
用法:
在任何 component.ts
canonicalLink:string;
constructor(private sanitizer: DomSanitizer) { }
//In oninit or when your data is ready, generate canonical link
ngOnInit() {
this.blogsService.getBlog(this.blogId).subscribe(data => {
let canLink = "https://example.com/blog/"+data.blogId;
// You can use pipe for sanitizing but lets do it here
this.canonicalLink = this.sanitizer.bypassSecurityTrustResourceUrl(canLink);
});
}
在任何 component.html 模板中:
<div *ngIf="canonicalLink">
<link rel="canonical" appMoveToHead [attr.href]="canonicalLink" />
</div>
<div>
<!-- Other template html -->
</div>
这样您就可以使用数据绑定和所有其他内容,并像对待模板中的任何其他元素一样对待 meta
、link
等。
例如-
<link rel="amphtml" moveToHead [attr.href]="ampUrl">
此方法也适用于 Angular 通用 (SSR)。
请参考下面link -
这适用于 Angular 8 或 9,并将规范 URL 添加到您网站的每个页面。
- 创建规范服务:
// shared/canonical/canonical.service.ts
import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class CanonicalService {
constructor(@Inject(DOCUMENT) private dom) {}
setCanonicalURL(url?: string) {
const canURL = url == undefined ? this.dom.URL : url;
const link: HTMLLinkElement = this.dom.createElement('link');
link.setAttribute('rel', 'canonical');
this.dom.head.appendChild(link);
link.setAttribute('href', canURL);
}
}
- 引用规范服务并在应用程序组件中调用它
// app.component.ts
import { CanonicalService } from './shared/services/canonical/canonical.service';
...
ngOnInit() {
this.canonicalService.setCanonicalURL();
}
...
要销毁现有的 link,请在创建新的之前调用此方法:
destroyLinkForCanonicalURL() {
const els = this.document.querySelectorAll('link[rel=\'canonical\']');
for (let i = 0, l = els.length; i < l; i++) {
const el = els[i];
el.remove();
}
}
与 解决方案完美结合。
它还可以防止在 SSR 模式下复制 links。
如何在 angular 5 中动态添加规范 link
<link rel="canonical" href="http://foobar.com/gotcah"/>
我得到了解决方案, 创建 link 服务(例如:link.service.ts)并粘贴以下代码:
import { Injectable, Optional, RendererFactory2, ViewEncapsulation, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/platform-browser';
@Injectable()
export class LinkService {
constructor(
private rendererFactory: RendererFactory2,
@Inject(DOCUMENT) private document
) {
}
/**
* Inject the State into the bottom of the <head>
*/
addTag(tag: LinkDefinition, forceCreation?: boolean) {
try {
const renderer = this.rendererFactory.createRenderer(this.document, {
id: '-1',
encapsulation: ViewEncapsulation.None,
styles: [],
data: {}
});
const link = renderer.createElement('link');
const head = this.document.head;
const selector = this._parseSelector(tag);
if (head === null) {
throw new Error('<head> not found within DOCUMENT.');
}
Object.keys(tag).forEach((prop: string) => {
return renderer.setAttribute(link, prop, tag[prop]);
});
// [TODO]: get them to update the existing one (if it exists) ?
renderer.appendChild(head, link);
} catch (e) {
console.error('Error within linkService : ', e);
}
}
private _parseSelector(tag: LinkDefinition): string {
// Possibly re-work this
const attr: string = tag.rel ? 'rel' : 'hreflang';
return `${attr}="${tag[attr]}"`;
}
}
export declare type LinkDefinition = {
charset?: string;
crossorigin?: string;
href?: string;
hreflang?: string;
media?: string;
rel?: string;
rev?: string;
sizes?: string;
target?: string;
type?: string;
} & {
[prop: string]: string;
};
在组件中导入服务:
import { LinkService } from '../link.service';
constructor(private linkService: LinkService) {
this.linkService.addTag( { rel: 'canonical', href: 'url here'} );
}
请参考下面link :
面对同样的问题,我四处搜索并找到了有关如何执行此操作的指南:
https://www.concretepage.com/angular/angular-title-service-and-canonical-url
虽然它使用的是 Angular 6,但我认为它向后兼容 5。
它基本上建议创建一个服务 (SEOService),以便在注入的任何地方创建规范 link。它将 Angular DOCUMENT
对象注入到服务中,并创建规范的 link 元素作为 HTMLLinkElement
.
注意解决方案 prerendering/serverside 呈现友好 - 因此,如果您希望更好地控制应用程序中页面的 SEO,我相信这就是您想要的。
这里是对文章中服务的最小重写:
seo.service.ts
import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class SeoService {
constructor(@Inject(DOCUMENT) private doc) {}
createLinkForCanonicalURL() {
let link: HTMLLinkElement = this.doc.createElement('link');
link.setAttribute('rel', 'canonical');
this.doc.head.appendChild(link);
link.setAttribute('href', this.doc.URL);
}
}
这里重写了使用该服务的组件:
data.component.ts
import { Component, OnInit } from '@angular/core';
import { SeoService } from './seo.service';
@Component({
selector: 'app-data',
templateUrl: './data.component.html'
})
export class DataComponent implements OnInit {
constructor(private seoService: SeoService) { }
ngOnInit() {
this.createLinkForCanonicalURL();
}
createLinkForCanonicalURL() {
this.seoService.createLinkForCanonicalURL();
}
}
您可以简单地让 createLinkForCanonicalURL()
方法采用 URL 的可选参数作为页面的规范参考,以实现完全控制。
如果您想动态添加规范 link 然后创建一个简单的 moveToHead 指令,如下所示:
@Directive({
selector: '[appMoveToHead]'
})
export class MoveToHeadDirective implements OnDestroy, OnInit {
constructor(private renderer: Renderer2,
private elRef: ElementRef,
@Inject(DOCUMENT) private document: Document) {
}
ngOnInit(): void {
this.renderer.appendChild(this.document.head, this.elRef.nativeElement);
this.renderer.removeAttribute(this.elRef.nativeElement, 'appmovetohead');
}
ngOnDestroy(): void {
this.renderer.removeChild(this.document.head, this.elRef.nativeElement);
}
}
在这里,当用户导航到另一个页面时,我们将从 DOM 中删除规范标签。我们在 MoveToHead 指令的 ngOnDestroy()
中执行此操作。因此,处理了新页面中存在先前规范标签的情况。
用法: 在任何 component.ts
canonicalLink:string;
constructor(private sanitizer: DomSanitizer) { }
//In oninit or when your data is ready, generate canonical link
ngOnInit() {
this.blogsService.getBlog(this.blogId).subscribe(data => {
let canLink = "https://example.com/blog/"+data.blogId;
// You can use pipe for sanitizing but lets do it here
this.canonicalLink = this.sanitizer.bypassSecurityTrustResourceUrl(canLink);
});
}
在任何 component.html 模板中:
<div *ngIf="canonicalLink">
<link rel="canonical" appMoveToHead [attr.href]="canonicalLink" />
</div>
<div>
<!-- Other template html -->
</div>
这样您就可以使用数据绑定和所有其他内容,并像对待模板中的任何其他元素一样对待 meta
、link
等。
例如-
<link rel="amphtml" moveToHead [attr.href]="ampUrl">
此方法也适用于 Angular 通用 (SSR)。
请参考下面link -
这适用于 Angular 8 或 9,并将规范 URL 添加到您网站的每个页面。
- 创建规范服务:
// shared/canonical/canonical.service.ts
import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Injectable({
providedIn: 'root'
})
export class CanonicalService {
constructor(@Inject(DOCUMENT) private dom) {}
setCanonicalURL(url?: string) {
const canURL = url == undefined ? this.dom.URL : url;
const link: HTMLLinkElement = this.dom.createElement('link');
link.setAttribute('rel', 'canonical');
this.dom.head.appendChild(link);
link.setAttribute('href', canURL);
}
}
- 引用规范服务并在应用程序组件中调用它
// app.component.ts
import { CanonicalService } from './shared/services/canonical/canonical.service';
...
ngOnInit() {
this.canonicalService.setCanonicalURL();
}
...
要销毁现有的 link,请在创建新的之前调用此方法:
destroyLinkForCanonicalURL() {
const els = this.document.querySelectorAll('link[rel=\'canonical\']');
for (let i = 0, l = els.length; i < l; i++) {
const el = els[i];
el.remove();
}
}
与
它还可以防止在 SSR 模式下复制 links。