前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Angular Meta Service 详解

Angular Meta Service 详解

作者头像
阿宝哥
发布2019-11-05 15:51:18
1.2K0
发布2019-11-05 15:51:18
举报
文章被收录于专栏:全栈修仙之路全栈修仙之路

Meta 标签

The tag provides metadata about the HTML document. Metadata will not be displayed on the page, but will be machine parsable.

Metadata 中文名叫元数据,是用于描述数据的数据。它不会显示在页面上,但是机器却可以识别。meta 常用于定义页面的说明,关键字,最后修改日期,和其它的元数据。这些元数据将服务于浏览器,搜索引擎和其它网络服务。

meta 标签共有两个属性,分别是 name 属性和 http-equiv 属性:

  • name:主要用于描述网页,比如网页的关键词,网站描述等。与之对应的属性值为 content,content 中的内容是对 name 填入类型的具体描述,便于搜索引擎抓取。比如我们常见的 viewport:
代码语言:javascript
复制
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1">
  • http-equiv:相当于文件的头作用,用于向浏览器传递一些有用的信息,以帮助正确地显示网页内容,与之对应的属性为 content。
代码语言:javascript
复制
<meta http-equiv="X-UA-Compatible" content="IE=edge">

以上代码告诉 IE 浏览器,IE8/9 及以后的版本都会以最高版本 IE 来渲染页面。关于 HTML meta 标签的相关知识,这里就不再继续展开,感兴趣的同学可以阅读 HTML meta标签总结与属性使用介绍 这篇文章。

Meta Service 简介

为了让开发者能够方便地操作页面中的 Meta 信息,Angular 为我们提供 Meta 服务。该服务支持以下的方法:

首先要使用 Meta 服务,我们需要从 @angular/platform-browser 库导入 Meta 类,然后利用 Angular 依赖注入的机制,通过构造注入的方式注入 Meta 服务:

代码语言:javascript
复制
import { Injectable } from '@angular/core';
import { Meta } from '@angular/platform-browser';

@Injectable({
   providedIn: 'root'
})
export class MetaService { 
  constructor(private meta: Meta) { }
}
addTag()

addTag(tag: MetaDefinition, forceCreation: boolean = false): HTMLMetaElement | null

该方法用于在页面上添加一个 HTML Meta 标签,它接收两个参数:

  • tag:MetaDefinition 类型的对象
  • forceCreation:是否强制创建,默认为 false

tag 参数对应的 MetaDefinition 类型定义如下:

代码语言:javascript
复制
export type MetaDefinition = {
  charset?: string; 
  content?: string;
  httpEquiv?: string; 
  id?: string; 
  itemprop?: string;
  name?: string;
  property?: string;
  scheme?: string;
  url?: string;
} &
{
  // TODO(IgorMinar): this type looks wrong
  [prop: string]: string;
};

了解完上述的内容,我们来动手实践一下:

代码语言:javascript
复制
@Injectable({
  providedIn: "root"
})
export class MetaService {
  constructor(private meta: Meta) { }

  addTag() {
    this.meta.addTag({ name: 'description', content: 'Angular Meta Service' });
    this.meta.addTag({ name: 'keywords', content: 'Angular, RxJS, TypeScript' });
  }
}

上述代码我们通过调用 meta 服务的 addTag() 方法,创建了两个 Meta 标签。如果需要一次添加多个 meta 标签,我们可以调用 addTags() 方法。

addTags()

addTags(tags: MetaDefinition[], forceCreation: boolean = false): HTMLMetaElement[]

该方法用于一次性添加多个 HTML Meta 标签,它接收两个参数:

  • tags:MetaDefinition 类型的对象数组
  • forceCreation:是否强制创建,默认为 false
代码语言:javascript
复制
addTags() {
  this.meta.addTags([
    { name: 'description', content: 'Angular Meta Service' },
    { name: 'keywords', content: 'Angular, RxJS, TypeScript' }
  ]);
}

在创建完 HTML meta 标签,我们可以通过 getTag() 方法来获取对应的 HTMLMetaElement 对象。

getTag()

getTag(attrSelector: string): HTMLMetaElement | null

该方法用于获取 attrSelector 属性选择器对应的 HTMLMetaElement 对象,它接收一个参数,即属性选择器,比如我们需要获取 keywords meta 标签:

代码语言:javascript
复制
getMetaTag(){
  let metaEl: HTMLMetaElement = this.meta.getTag('name="keywords"');
  console.log(`Get keywords meta tag: ${metaEl}`);
}

当 getTag() 方法匹配不了 attrSelector 属性选择器时,会返回 null 对象。与 setTag() 类似,getTag() 方法也存在一个 getTags() 方法。

getTags()

getTags(attrSelector: string): HTMLMetaElement[]

该方法用于获取所有匹配 attrSelector 选择器的所有 HTMLMetaElement 对象:

代码语言:javascript
复制
getMetaTags() {
  let els: HTMLMetaElement[] = this.meta.getTags('name');
  els.forEach(el => {
    console.log(el);
    console.log(el.name);
    console.log(el.content);
  });
}

这时我们已经介绍完了如何创建和查找 HTMLMetaElement 对象,有时候在创建完 HTMLMetaElement 对象后,我们可能需要修改 HTMLMetaElement 对象,此时我们需要使用 updateTag() 方法。

updateTag()

updateTag(tag: MetaDefinition, selector?: string): HTMLMetaElement | null

该方法用于更新 HTML Meta 标签的信息,它接收两个参数:

  • tag:MetaDefinition 类型的对象
  • selector(可选):选择器
代码语言:javascript
复制
updateMetaTags() {
  this.meta.updateTag({
    name: 'description', 
    content: 'Updated: Angular Meta Service'
  });
  this.meta.updateTag({ name: 'keywords', content: 'Node.js, Angular' });
}

除了更新 HTML Meta 标签之外,我们也可以移除指定的 HTML Meta 标签。

removeTag()

removeTag(attrSelector: string): void

该方法用于移除匹配 attrSelector 属性选择器的 HTML Meta 标签:

代码语言:javascript
复制
removeMetaTags() {
  this.meta.removeTag('name="description"');
  this.meta.removeTag('name="keywords"');
}

最后我们来介绍 removeTagElement() 方法。

removeTagElement()

removeTagElement(meta: HTMLMetaElement): void

该方法用于移除 meta 参数对应的 HTML Meta 标签:

代码语言:javascript
复制
removeTagElement() {
  let keywords: HTMLMetaElement = this.meta.getTag('name="keywords"');
  this.meta.removeTagElement(keywords);
}

感兴趣的同学,可以浏览 Stackblitz 线上示例。下面我们来简单分析一下 Meta Service 的源码。

Meta Service 源码简析

Meta Service 类及构造函数
代码语言:javascript
复制
// packages/platform-browser/src/browser/meta.ts
@Injectable({providedIn: 'root', useFactory: createMeta, deps: []})
export class Meta {
  private _dom: DomAdapter;
  constructor(@Inject(DOCUMENT) private _doc: any) { 
      this._dom = getDOM(); // 获取DOM适配器
  }
}

通过观察 Injectable 装饰器的 Meta 元信息,我们知道 Meta 服务将被注册在根级注入器中,当首次获取 Meta 服务时,将使用 createMeta() 工厂方法创建对应的实例。

代码语言:javascript
复制
import {Inject, Injectable, inject} from '@angular/core';

export function createMeta() {
  return new Meta(inject(DOCUMENT));// 注意这里是小写的inject的哦
}

接下来我们从最简单的 addTag() 方法开始分析。

addTag()
代码语言:javascript
复制
addTag(tag: MetaDefinition, forceCreation: boolean = false): HTMLMetaElement|null {
  if (!tag) return null;
  return this._getOrCreateElement(tag, forceCreation);
}

这时我们知道其实在 addTag() 方法内部,最终是调用内部的私有方法 _getOrCreateElement() 来执行具体操作。_getOrCreateElement() 方法的具体实现如下:

代码语言:javascript
复制
private _getOrCreateElement(meta: MetaDefinition, forceCreation: boolean = false):
      HTMLMetaElement {
    if (!forceCreation) { // 非强制模式
      const selector: string = this._parseSelector(meta); // 解析选择器
      const elem: HTMLMetaElement = this.getTag(selector) !; // 获取选择器匹配的Meta元素
      // It's allowed to have multiple elements with the same name so it's not enough to
      // just check that element with the same name already present on the page. 
      // We also need to check if element has tag attributes
      if (elem && this._containsAttributes(meta, elem)) return elem;
    }
    // 调用Dom适配器的createElement()方法创建meta元素  
    const element: HTMLMetaElement = this._dom.createElement('meta') as HTMLMetaElement;
    this._setMetaElementAttributes(meta, element);
    // 获取head元素,添加新建的meta元素并返回该元素      
    const head = this._dom.getElementsByTagName(this._doc, 'head')[0];
    this._dom.appendChild(head, element);
    return element;
}

// 解析选择器
private _parseSelector(tag: MetaDefinition): string {
   const attr: string = tag.name ? 'name' : 'property';
   return `${attr}="${tag[attr]}"`;
}

// 设置Meta元素的属性
private _setMetaElementAttributes(tag: MetaDefinition, el: HTMLMetaElement): 
   HTMLMetaElement {
    Object.keys(tag).forEach((prop: string) => 
      this._dom.setAttribute(el, prop, tag[prop]));
    return el;
}

简单分析完 addTag(),我们再来看一下与它对应的 getTag() 方法。

getTag()
代码语言:javascript
复制
getTag(attrSelector: string): HTMLMetaElement|null {
  if (!attrSelector) return null; 
  return this._dom.querySelector(this._doc, `meta[${attrSelector}]`) || null;
}

该方法内部的实现也很简单,就是通过 DOM 适配器的 querySelector API 来实现元素匹配。对于前面的示例来说:

代码语言:javascript
复制
let metaEl: HTMLMetaElement = this.meta.getTag('name="keywords"');

内部会转换为:

代码语言:javascript
复制
return this._dom.querySelector(this._doc, "meta[name='keywords')" || null;

新增和查询的方法介绍完,我们来继续分析一下 updateTag() 方法。

updateTag()
代码语言:javascript
复制
updateTag(tag: MetaDefinition, selector?: string): HTMLMetaElement|null {
    if (!tag) return null;
    selector = selector || this._parseSelector(tag); // 解析选择器
    const meta: HTMLMetaElement = this.getTag(selector) !; // 获取选择器对应的 Meta 元素
    if (meta) { // 若已存在,则更新对应的属性
      return this._setMetaElementAttributes(tag, meta);
    }
    return this._getOrCreateElement(tag, true); // 否则在force模式下,创建 Meta 元素
}

最后再来看一下 removeTag() 方法,顾名思义就是用来移除指定的 Meta 元素。

removeTag()
代码语言:javascript
复制
removeTag(attrSelector: string): void { 
    this.removeTagElement(this.getTag(attrSelector) !);
}

removeTagElement(meta: HTMLMetaElement): void {
    if (meta) {
      this._dom.remove(meta);
    }
}

参考资源

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018/08/30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Meta 标签
  • Meta Service 简介
    • addTag()
      • addTags()
        • getTag()
          • getTags()
            • updateTag()
              • removeTag()
                • removeTagElement()
                • Meta Service 源码简析
                  • Meta Service 类及构造函数
                    • addTag()
                      • getTag()
                        • updateTag()
                          • removeTag()
                          • 参考资源
                          相关产品与服务
                          文档服务
                          文档服务(Document Service,DS)是腾讯云数据万象提供云上文档处理服务,支持多种类型的文件生成图片或 html 格式的预览,可以解决文档内容的页面展示问题,满足 PC、App 等多端的文档在线浏览需求。同时,本产品还提供文本隐私筛查能力,可以有效识别文本中的身份证号、银行卡号、手机号等敏感数据,满足数据可用性和隐私保护的各种要求。
                          领券
                          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档